name: Build # Builds the image on every push to main and pushes it to Gitea's container # registry as "latest" (after first re-tagging the current "latest" as # "previous", for a one-step-back rollback point -- no-ops on the very first # run, when there's no existing "latest" to promote). Deliberately just # "latest"/"previous", not per-commit tags, to avoid accumulating history. # See release.yml for tagged releases (git tag -> matching image tag). # # This project's CI/CD scope is intentionally just test/build/push -- # deployment is being split into a separate project. # # Requires secrets.BUILD_API_TOKEN -- a personal access token # (write:package scope) from the pushing account, stored manually as a repo # secret. The auto-injected secrets.GITEA_TOKEN does NOT work for this: it # never grants package-registry access regardless of the workflow's own # `permissions:` block -- a known Gitea limitation, not a config mistake # (https://github.com/go-gitea/gitea/issues/23642). on: push: branches: [main] workflow_dispatch: jobs: build-and-push: runs-on: ubuntu-latest # Relies on the Gitea runner's Docker daemon being reachable from job # containers, which it is out of the box -- no extra runner config needed. container: image: docker:cli steps: # actions/checkout is a JS action; docker:cli is Alpine-based and has # no node on PATH by default (same issue fixed in ci.yml). - name: Install Node run: apk add --no-cache nodejs - uses: actions/checkout@v4 - name: Log in to the container registry env: BUILD_API_TOKEN: ${{ secrets.BUILD_API_TOKEN }} run: echo "$BUILD_API_TOKEN" | docker login code.aneur.in -u "${{ gitea.actor }}" --password-stdin - name: Promote the current "latest" to "previous" run: | IMAGE="code.aneur.in/${{ gitea.repository }}" if docker pull "$IMAGE:latest"; then docker tag "$IMAGE:latest" "$IMAGE:previous" docker push "$IMAGE:previous" fi - name: Build and push "latest" run: | IMAGE="code.aneur.in/${{ gitea.repository }}:latest" docker build -t "$IMAGE" . docker push "$IMAGE"