diff --git a/.gitea/workflows/release-docker.yml b/.gitea/workflows/release-docker.yml index 98d8062..d10cea1 100644 --- a/.gitea/workflows/release-docker.yml +++ b/.gitea/workflows/release-docker.yml @@ -35,8 +35,12 @@ jobs: TAGS="lerkolabs/uptop:${TAG}" TAGS="${TAGS},lerkolabs/uptop:sha-${SHORT_SHA}" + # :latest only for real releases — rc rehearsal tags must not move it if [ "${{ github.ref_type }}" = "tag" ]; then - TAGS="${TAGS},lerkolabs/uptop:latest" + case "$TAG" in + *-*) ;; + *) TAGS="${TAGS},lerkolabs/uptop:latest" ;; + esac fi echo "tags=$TAGS" >> "$GITHUB_OUTPUT" @@ -52,6 +56,26 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + # Scan must gate the push: build amd64 locally, scan it, and only then run + # the multi-arch push (amd64 layers come from the builder cache, so the + # second build only adds the arm64 work). + - name: Build for scan (amd64, local) + uses: docker/build-push-action@v5 + with: + context: . + load: true + platforms: linux/amd64 + tags: uptop-scan:${{ steps.meta.outputs.tag }} + build-args: | + VERSION=${{ steps.meta.outputs.tag }} + COMMIT=${{ github.sha }} + BUILD_DATE=${{ github.event.head_commit.timestamp }} + + - name: Scan image for CVEs + run: | + curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.114.0 + grype uptop-scan:${{ steps.meta.outputs.tag }} --fail-on critical --output table + - name: Build and push uses: docker/build-push-action@v5 with: @@ -66,11 +90,6 @@ jobs: COMMIT=${{ github.sha }} BUILD_DATE=${{ github.event.head_commit.timestamp }} - - name: Scan image for CVEs - run: | - curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.114.0 - grype lerkolabs/uptop:${{ steps.meta.outputs.tag }} --fail-on critical --output table - - name: Update Docker Hub description uses: peter-evans/dockerhub-description@v4 with: diff --git a/.github/workflows/mirror-release.yml b/.github/workflows/mirror-release.yml index d25c723..8c085db 100644 --- a/.github/workflows/mirror-release.yml +++ b/.github/workflows/mirror-release.yml @@ -19,22 +19,29 @@ jobs: run: | API="https://gitea.lerkolabs.com/api/v1/repos/lerkolabs/uptop/releases/tags/${TAG}" - for i in $(seq 1 20); do + # 40 x 30s = 20 min: the Gitea release can queue behind the ~18-min + # Docker job on the single runner. Asset count must hold steady for + # two consecutive polls — GoReleaser uploads one file at a time, and + # mirroring mid-upload would publish a partial asset set. + PREV_COUNT=0 + ASSET_COUNT=0 + for i in $(seq 1 40); do if RESPONSE=$(curl -sf "$API" 2>/dev/null); then ASSET_COUNT=$(echo "$RESPONSE" | jq '.assets | length') - if [ "$ASSET_COUNT" -gt 0 ]; then - echo "Found release with $ASSET_COUNT assets" + if [ "$ASSET_COUNT" -gt 0 ] && [ "$ASSET_COUNT" -eq "$PREV_COUNT" ]; then + echo "Found release with $ASSET_COUNT assets (stable)" break fi - echo "Release exists but no assets yet... attempt $i/20" + echo "Release has $ASSET_COUNT assets (was $PREV_COUNT)... attempt $i/40" + PREV_COUNT="$ASSET_COUNT" else - echo "Waiting for Gitea release... attempt $i/20" + echo "Waiting for Gitea release... attempt $i/40" fi sleep 30 done if [ -z "$RESPONSE" ] || [ "$ASSET_COUNT" -eq 0 ]; then - echo "::error::Gitea release for ${TAG} not found or has no assets after 10 minutes" + echo "::error::Gitea release for ${TAG} not found or has no assets after 20 minutes" exit 1 fi