mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-06-09 06:04:12 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d6215f3ae | |||
| 9c82a7036b | |||
| 784e215d78 | |||
| 3849750cf3 | |||
| 9e0215457f | |||
| 2bd474adc2 | |||
| 14b1936f58 | |||
| 3b7272a872 | |||
| a58894a757 | |||
| 461e4a545b | |||
| 28fea864b8 | |||
| 2827620cfe |
@@ -1,4 +1,3 @@
|
||||
---
|
||||
name: CI
|
||||
|
||||
on:
|
||||
@@ -11,6 +10,7 @@ on:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# see: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#using-a-specific-shell
|
||||
shell: bash --noprofile --norc -eo pipefail {0}
|
||||
|
||||
env:
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
make docker-image
|
||||
- name: "Unit Tests"
|
||||
run: |
|
||||
make docker-unit-test
|
||||
make docker-unit-tests
|
||||
mkdir -p out/coverage
|
||||
mv unit.out out/coverage/
|
||||
- uses: actions/upload-artifact@v4
|
||||
@@ -140,7 +140,7 @@ jobs:
|
||||
|
||||
- name: "Upload Code Coverage"
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
uses: codecov/codecov-action@v7.0.0
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: coverage.txt
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ aptly version: 1.5.0+189+g0fc90dff
|
||||
|
||||
In order to run aptly unit tests, enter the following:
|
||||
```
|
||||
make docker-unit-test
|
||||
make docker-unit-tests
|
||||
```
|
||||
|
||||
#### Running system tests
|
||||
|
||||
@@ -182,6 +182,9 @@ binaries: prepare swagger ## Build binary releases (FreeBSD, macOS, Linux gener
|
||||
docker-image: ## Build aptly-dev docker image
|
||||
@docker build -f system/Dockerfile . -t aptly-dev
|
||||
|
||||
docker-image-test: # Build aptly-test docker image for testing
|
||||
@docker build -f docker/test.Dockerfile . -t aptly-test
|
||||
|
||||
docker-image-no-cache: ## Build aptly-dev docker image (no cache)
|
||||
@docker build --no-cache -f system/Dockerfile . -t aptly-dev
|
||||
|
||||
@@ -194,7 +197,7 @@ docker-shell: ## Run aptly and other commands in docker container
|
||||
docker-deb: ## Build debian packages in docker container
|
||||
@$(DOCKER_RUN) -t aptly-dev /work/src/system/docker-wrapper dpkg DEBARCH=amd64
|
||||
|
||||
docker-unit-test: ## Run unit tests in docker container (add TEST=regex to specify which tests to run)
|
||||
docker-unit-tests: ## Run unit tests in docker container (add TEST=regex to specify which tests to run)
|
||||
$(DOCKER_RUN) -t --tmpfs /smallfs:rw,size=1m aptly-dev /work/src/system/docker-wrapper \
|
||||
azurite-start \
|
||||
AZURE_STORAGE_ENDPOINT=http://127.0.0.1:10000/devstoreaccount1 \
|
||||
|
||||
+14
-6
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -298,16 +299,23 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
|
||||
multiDist = *b.MultiDist
|
||||
}
|
||||
|
||||
// Non-MultiDist publishes share a single pool/ directory under the
|
||||
// prefix. Lock at the prefix level so that concurrent publish/drop
|
||||
// operations on sibling distributions cannot race during cleanup.
|
||||
if !multiDist {
|
||||
// Pre-register the published repo key in resources so that concurrent
|
||||
// POST requests for the same prefix/distribution are serialized by the
|
||||
// task queue rather than racing on CheckDuplicate + Add.
|
||||
if b.Distribution != "" {
|
||||
storagePrefix := prefix
|
||||
if storage != "" {
|
||||
storagePrefix = storage + ":" + prefix
|
||||
}
|
||||
|
||||
resources = append(resources, deb.PrefixPoolLockKey(storagePrefix))
|
||||
resources = append(resources, "U"+storagePrefix+">>"+b.Distribution)
|
||||
// Non-MultiDist publishes share a single pool/ directory under the
|
||||
// prefix. Lock at the prefix level so that concurrent publish/drop
|
||||
// operations on sibling distributions cannot race during cleanup.
|
||||
if !multiDist {
|
||||
resources = append(resources, deb.PrefixPoolLockKey(storagePrefix))
|
||||
}
|
||||
} else {
|
||||
log.Printf("distribution not specified for publish to prefix '%s' - unable to lock ", prefix)
|
||||
}
|
||||
|
||||
taskName := fmt.Sprintf("Publish %s repository %s/%s with components \"%s\" and sources \"%s\"",
|
||||
|
||||
@@ -429,18 +429,48 @@ func (s *PublishedFileMissingSuite) TestIdenticalPackageRace(c *C) {
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
s.httpRequest(c, "POST", fmt.Sprintf("/api/repos/%s/file/%s?noRemove=0", repos[0], uploadID1), nil)
|
||||
//time.Sleep(5 * time.Millisecond)
|
||||
c.Logf("[iter %d] Import A", iter)
|
||||
resp := s.httpRequest(c, "POST", fmt.Sprintf("/api/repos/%s/file/%s?noRemove=0", repos[0], uploadID1), nil)
|
||||
c.Logf("[iter %d] Import A complete: %d", iter, resp.Code)
|
||||
|
||||
updateBody, _ := json.Marshal(gin.H{"Signing": gin.H{"Skip": true}, "ForceOverwrite": true, "SkipBz2": true})
|
||||
s.httpRequest(c, "PUT", fmt.Sprintf("/api/publish/identical/%s", dists[0]), updateBody)
|
||||
c.Logf("[iter %d] Publish A", iter)
|
||||
resp = s.httpRequest(c, "PUT", fmt.Sprintf("/api/publish/identical/%s", dists[0]), updateBody)
|
||||
c.Logf("[iter %d] Publish A complete: %d", iter, resp.Code)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
s.httpRequest(c, "POST", fmt.Sprintf("/api/repos/%s/file/%s?noRemove=0", repos[1], uploadID2), nil)
|
||||
//time.Sleep(7 * time.Millisecond)
|
||||
c.Logf("[iter %d] Import B", iter)
|
||||
resp := s.httpRequest(c, "POST", fmt.Sprintf("/api/repos/%s/file/%s?noRemove=0", repos[1], uploadID2), nil)
|
||||
c.Logf("[iter %d] Import B complete: %d", iter, resp.Code)
|
||||
|
||||
updateBody, _ := json.Marshal(gin.H{"Signing": gin.H{"Skip": true}, "ForceOverwrite": true, "SkipBz2": true})
|
||||
s.httpRequest(c, "PUT", fmt.Sprintf("/api/publish/identical/%s", dists[1]), updateBody)
|
||||
c.Logf("[iter %d] Publish B", iter)
|
||||
resp = s.httpRequest(c, "PUT", fmt.Sprintf("/api/publish/identical/%s", dists[1]), updateBody)
|
||||
c.Logf("[iter %d] Publish B complete: %d", iter, resp.Code)
|
||||
}()
|
||||
|
||||
//go func() {
|
||||
//defer wg.Done()
|
||||
//time.Sleep(15 * time.Millisecond)
|
||||
//updateBody, _ := json.Marshal(gin.H{"Signing": gin.H{"Skip": true}, "ForceOverwrite": true, "SkipBz2": true})
|
||||
//c.Logf("[iter %d] Publish A", iter)
|
||||
//resp := s.httpRequest(c, "PUT", fmt.Sprintf("/api/publish/identical/%s", dists[0]), updateBody)
|
||||
//c.Logf("[iter %d] Publish A complete: %d", iter, resp.Code)
|
||||
//}()
|
||||
|
||||
//go func() {
|
||||
//defer wg.Done()
|
||||
//time.Sleep(18 * time.Millisecond)
|
||||
//updateBody, _ := json.Marshal(gin.H{"Signing": gin.H{"Skip": true}, "ForceOverwrite": true, "SkipBz2": true})
|
||||
//c.Logf("[iter %d] Publish B", iter)
|
||||
//resp := s.httpRequest(c, "PUT", fmt.Sprintf("/api/publish/identical/%s", dists[1]), updateBody)
|
||||
//c.Logf("[iter %d] Publish B complete: %d", iter, resp.Code)
|
||||
//}()
|
||||
|
||||
wg.Wait()
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
c.Logf("[iter %d] All operations complete", iter)
|
||||
|
||||
+15
-28
@@ -209,37 +209,24 @@ func apiSnapshotsCreate(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// Merge packages from all source snapshots
|
||||
var refList *deb.PackageRefList
|
||||
if len(freshSources) > 0 {
|
||||
refList = freshSources[0].RefList()
|
||||
for i := 1; i < len(freshSources); i++ {
|
||||
refList = refList.Merge(freshSources[i].RefList(), true, false)
|
||||
list := deb.NewPackageList()
|
||||
|
||||
// verify package refs and build package list using fresh factory
|
||||
for _, ref := range b.PackageRefs {
|
||||
p, err := taskPackageCollection.ByKey([]byte(ref))
|
||||
if err != nil {
|
||||
if err == database.ErrNotFound {
|
||||
return &task.ProcessReturnValue{Code: http.StatusNotFound, Value: nil}, fmt.Errorf("package %s: %s", ref, err)
|
||||
}
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, err
|
||||
}
|
||||
err = list.Add(p)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusBadRequest, Value: nil}, err
|
||||
}
|
||||
} else {
|
||||
refList = deb.NewPackageRefList()
|
||||
}
|
||||
|
||||
// Add any explicitly specified package refs on top
|
||||
if len(b.PackageRefs) > 0 {
|
||||
list := deb.NewPackageList()
|
||||
for _, ref := range b.PackageRefs {
|
||||
p, err := taskPackageCollection.ByKey([]byte(ref))
|
||||
if err != nil {
|
||||
if err == database.ErrNotFound {
|
||||
return &task.ProcessReturnValue{Code: http.StatusNotFound, Value: nil}, fmt.Errorf("package %s: %s", ref, err)
|
||||
}
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, err
|
||||
}
|
||||
err = list.Add(p)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusBadRequest, Value: nil}, err
|
||||
}
|
||||
}
|
||||
refList = refList.Merge(deb.NewPackageRefListFromPackageList(list), true, false)
|
||||
}
|
||||
|
||||
snapshot = deb.NewSnapshotFromRefList(b.Name, freshSources, refList, b.Description)
|
||||
snapshot = deb.NewSnapshotFromRefList(b.Name, freshSources, deb.NewPackageRefListFromPackageList(list), b.Description)
|
||||
|
||||
err = taskSnapshotCollection.Add(snapshot)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
FROM aptly-dev
|
||||
|
||||
ADD --chown=aptly:aptly . /work/src/
|
||||
|
||||
# Pre-populate the Go module cache so go mod verify works offline
|
||||
RUN chown aptly /work/src && mkdir -p /work/src/.go && chown aptly /work/src/.go && \
|
||||
cd /work/src && sudo -u aptly GOPATH=/work/src/.go GOCACHE=/work/src/.go/cache go mod download
|
||||
@@ -1207,10 +1207,11 @@ class PublishSwitchAPITestSnapshot(APITest):
|
||||
self.check_equal(all_repos.status_code, 200)
|
||||
self.check_in(repo_expected, all_repos.json())
|
||||
|
||||
# FIXME: what should exist here ? publish snapshot of snapshot
|
||||
self.check_not_exists(
|
||||
"public/" + prefix + "/pool/main/b/boost-defaults/libboost-program-options-dev_1.49.0.1_i386.deb")
|
||||
self.check_exists("public/" + prefix +
|
||||
"/pool/main/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc")
|
||||
self.check_not_exists("public/" + prefix +
|
||||
"/pool/main/p/pyspi/pyspi-0.6.1-1.3.stripped.dsc")
|
||||
|
||||
task = self.delete_task("/api/publish/" + prefix + "/wheezy")
|
||||
self.check_task(task)
|
||||
|
||||
Reference in New Issue
Block a user