diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..0db5542 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,104 @@ +name: CI + +on: + pull_request: + branches: [main] + # sidecar/ is the only Go module in this repo; skip CI for changes that + # cannot affect it (web/, ansible/, docs). + paths: + - "sidecar/**" + - ".github/workflows/ci.yaml" + +# Cancel in-progress runs for the same ref (PR or branch) when new commits land. +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +env: + GO_VERSION: "1.26" + +defaults: + run: + working-directory: sidecar + +jobs: + lint: + name: Lint & format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + check-latest: true + cache-dependency-path: sidecar/go.sum + + - name: Verify gofmt + run: | + unformatted=$(gofmt -l .) + if [ -n "$unformatted" ]; then + echo "::error::The following files are not gofmt-formatted:" + echo "$unformatted" + echo "Run 'gofmt -w .' to fix." + exit 1 + fi + + - name: go vet + run: go vet ./... + + - name: Verify go.mod is tidy + run: | + go mod tidy + if ! git diff --exit-code -- go.mod go.sum; then + echo "::error::go.mod/go.sum are not tidy. Run 'go mod tidy' and commit the result." + exit 1 + fi + + - name: golangci-lint + uses: golangci/golangci-lint-action@v9 + with: + version: v2.12.2 + # `defaults.run` does not apply to actions, so point it at the module. + working-directory: sidecar + test: + name: Test + runs-on: ubuntu-latest + + # No service container: internal/redistest starts its own Redis on the + # runner's Docker daemon. GitHub sets CI=true, which makes it fail rather + # than skip, so the persistence layer cannot drop out of this job. + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + check-latest: true + cache-dependency-path: sidecar/go.sum + + - name: Run tests (race + coverage) + run: go test -race -coverprofile=cover.out -covermode=atomic ./... + + - name: Coverage summary + run: go tool cover -func=cover.out | tail -1 + + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + check-latest: true + cache-dependency-path: sidecar/go.sum + + - name: go build + env: + CGO_ENABLED: "0" + run: go build -ldflags="-s -w" ./... diff --git a/.github/workflows/govulncheck.yaml b/.github/workflows/govulncheck.yaml new file mode 100644 index 0000000..72206fd --- /dev/null +++ b/.github/workflows/govulncheck.yaml @@ -0,0 +1,42 @@ +name: Vulnerability check + +on: + pull_request: + branches: [main] + # sidecar/ is the only Go module in this repo. + paths: + - "sidecar/**" + - ".github/workflows/govulncheck.yaml" + schedule: + # Weekly scan so newly disclosed CVEs in pinned deps surface even + # without a code change. Mondays at 07:00 UTC. + - cron: "0 7 * * 1" + +concurrency: + group: govulncheck-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +defaults: + run: + working-directory: sidecar + +jobs: + govulncheck: + name: govulncheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-go@v6 + with: + go-version: "1.26" + check-latest: true + cache-dependency-path: sidecar/go.sum + + - name: Run govulncheck + run: | + go install golang.org/x/vuln/cmd/govulncheck@latest + govulncheck ./... diff --git a/sidecar/Dockerfile b/sidecar/Dockerfile index 3b2a08a..b1cabd1 100644 --- a/sidecar/Dockerfile +++ b/sidecar/Dockerfile @@ -65,7 +65,7 @@ ARG BUILD_DATE LABEL org.opencontainers.image.title="zot-ephemeral-ttl" \ org.opencontainers.image.description="Tag-driven TTL sidecar for zot. Subscribes to image.updated CloudEvents and DELETEs expired manifests." \ - org.opencontainers.image.source="https://github.com/nullbytelabs/zot-ephemeral-ttl" \ + org.opencontainers.image.source="https://github.com/replicatedhq/ttl.sh" \ org.opencontainers.image.licenses="Apache-2.0" \ org.opencontainers.image.version="${VERSION}" \ org.opencontainers.image.revision="${COMMIT}" \ diff --git a/sidecar/cmd/zot-ephemeral-ttl/main.go b/sidecar/cmd/zot-ephemeral-ttl/main.go index e4b10f5..ff685e3 100644 --- a/sidecar/cmd/zot-ephemeral-ttl/main.go +++ b/sidecar/cmd/zot-ephemeral-ttl/main.go @@ -9,8 +9,8 @@ import ( "os/signal" "syscall" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/app" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/config" + "github.com/replicatedhq/ttl.sh/sidecar/internal/app" + "github.com/replicatedhq/ttl.sh/sidecar/internal/config" ) // Build metadata, set via -ldflags "-X main.version=..." in the Dockerfile. diff --git a/sidecar/go.mod b/sidecar/go.mod index 8c6f48b..6cbdb13 100644 --- a/sidecar/go.mod +++ b/sidecar/go.mod @@ -1,4 +1,4 @@ -module github.com/nullbytelabs/zot-ephemeral-ttl +module github.com/replicatedhq/ttl.sh/sidecar go 1.26 diff --git a/sidecar/internal/app/app.go b/sidecar/internal/app/app.go index 0082b50..9c68570 100644 --- a/sidecar/internal/app/app.go +++ b/sidecar/internal/app/app.go @@ -13,11 +13,11 @@ import ( "net/http" "time" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/config" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/reaper" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/registry" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/server" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/store" + "github.com/replicatedhq/ttl.sh/sidecar/internal/config" + "github.com/replicatedhq/ttl.sh/sidecar/internal/reaper" + "github.com/replicatedhq/ttl.sh/sidecar/internal/registry" + "github.com/replicatedhq/ttl.sh/sidecar/internal/server" + "github.com/replicatedhq/ttl.sh/sidecar/internal/store" ) // storeBackend is the union of persistence capabilities app injects into the diff --git a/sidecar/internal/app/app_test.go b/sidecar/internal/app/app_test.go index 5858093..4b149d2 100644 --- a/sidecar/internal/app/app_test.go +++ b/sidecar/internal/app/app_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/config" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/redistest" + "github.com/replicatedhq/ttl.sh/sidecar/internal/config" + "github.com/replicatedhq/ttl.sh/sidecar/internal/redistest" ) // The startup-path test needs a real Redis; redistest starts one per package. diff --git a/sidecar/internal/reaper/reaper.go b/sidecar/internal/reaper/reaper.go index 986512d..35f36a5 100644 --- a/sidecar/internal/reaper/reaper.go +++ b/sidecar/internal/reaper/reaper.go @@ -9,7 +9,7 @@ import ( "log" "time" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/store" + "github.com/replicatedhq/ttl.sh/sidecar/internal/store" ) // Store is the subset of the persistence layer the reaper needs. diff --git a/sidecar/internal/reaper/reaper_test.go b/sidecar/internal/reaper/reaper_test.go index e1c4aab..e4c4cc1 100644 --- a/sidecar/internal/reaper/reaper_test.go +++ b/sidecar/internal/reaper/reaper_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/store" + "github.com/replicatedhq/ttl.sh/sidecar/internal/store" ) // In-memory fakes for the reaper's two dependencies. No real DB, no real HTTP. diff --git a/sidecar/internal/server/server.go b/sidecar/internal/server/server.go index 3baad2b..93f18cb 100644 --- a/sidecar/internal/server/server.go +++ b/sidecar/internal/server/server.go @@ -8,8 +8,8 @@ import ( "net/http" "time" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/events" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/ttl" + "github.com/replicatedhq/ttl.sh/sidecar/internal/events" + "github.com/replicatedhq/ttl.sh/sidecar/internal/ttl" ) // Store is the subset of the persistence layer the server needs. diff --git a/sidecar/internal/server/server_test.go b/sidecar/internal/server/server_test.go index 22f70dc..2439285 100644 --- a/sidecar/internal/server/server_test.go +++ b/sidecar/internal/server/server_test.go @@ -12,8 +12,8 @@ import ( "testing" "time" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/events" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/store" + "github.com/replicatedhq/ttl.sh/sidecar/internal/events" + "github.com/replicatedhq/ttl.sh/sidecar/internal/store" ) // Server.Store is documented as safe for concurrent use, so the fake locks its diff --git a/sidecar/internal/store/store_test.go b/sidecar/internal/store/store_test.go index df21254..8f8f19b 100644 --- a/sidecar/internal/store/store_test.go +++ b/sidecar/internal/store/store_test.go @@ -9,7 +9,7 @@ import ( "github.com/redis/go-redis/v9" - "github.com/nullbytelabs/zot-ephemeral-ttl/internal/redistest" + "github.com/replicatedhq/ttl.sh/sidecar/internal/redistest" ) // These tests run against a real Redis, started for the package by redistest.