name: Release Image # Reusable workflow: called from ci.yml after all checks pass. # Can also be dispatched manually for rebuilds or tag overrides. # # Pushes to the Gitea container registry (the same host the workflow runs on) # using the auto-provisioned GITHUB_TOKEN. No external secrets required. on: workflow_call: inputs: image_tag: description: Optional tag override, defaults to sha- required: false type: string workflow_dispatch: inputs: image_tag: description: Optional tag override, defaults to sha- required: false type: string permissions: contents: read packages: write jobs: build-and-push: name: Build And Push Images runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v4 - id: registry name: Resolve Gitea registry host # GITHUB_SERVER_URL inside act_runner resolves to the *internal* Gitea # hostname (gitea:3000) which is not reachable from the job container. # Hardcode the externally-resolvable host instead. run: | echo "host=gitea.hartmut-noerenberg.com" >> "$GITHUB_OUTPUT" - name: Login to Gitea container registry # GITHUB_TOKEN is auto-provisioned by Gitea Actions for the running # workflow; no manual secret configuration required. run: | echo "${{ secrets.REGISTRY_TOKEN }}" | \ docker login "${{ steps.registry.outputs.host }}" \ -u "${{ github.actor }}" --password-stdin - id: vars name: Compute image refs run: | owner="$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" repo="$(basename '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" image_tag="${{ inputs.image_tag }}" if [ -z "${image_tag}" ]; then image_tag="sha-${GITHUB_SHA}" fi host="${{ steps.registry.outputs.host }}" echo "app_image=${host}/${owner}/${repo}-app:${image_tag}" >> "$GITHUB_OUTPUT" echo "migrator_image=${host}/${owner}/${repo}-migrator:${image_tag}" >> "$GITHUB_OUTPUT" # Guardrail anchor: target: runner # Use plain `docker build` against the host daemon (DooD) instead of # docker/build-push-action's buildx+buildkit container, which fails on # the QNAP host with `runc ... fchmodat2 AT_EMPTY_PATH: no such file or # directory` (older kernel rejects newer buildkit's runc syscalls). - name: Build and push app image run: | docker build \ -f ./Dockerfile.prod \ --target runner \ -t "${{ steps.vars.outputs.app_image }}" \ . docker push "${{ steps.vars.outputs.app_image }}" # Guardrail anchor: target: migrator - name: Build and push migrator image run: | docker build \ -f ./Dockerfile.prod \ --target migrator \ -t "${{ steps.vars.outputs.migrator_image }}" \ . docker push "${{ steps.vars.outputs.migrator_image }}" - name: Release summary run: | echo "App image: ${{ steps.vars.outputs.app_image }}" echo "Migrator image: ${{ steps.vars.outputs.migrator_image }}"