# ci-images/flutter-node/.gitea/workflows/build.yaml # # Daily check, build ONLY when an input actually changed. # # Inputs that define an image: upstream base digests + the Dockerfile itself. # Their combined hash is published as a marker tag `src-` next to the image. # If that tag already exists in the registry, this exact image was already built # and the run stops before doing any work. # # Tags pushed on a real build: # :stable moving, what runners pull by default # :YYYYMMDD immutable, for pinning / rollback # :src- marker, 856 bytes, makes the next check a single registry lookup name: build on: schedule: - cron: "0 3 * * *" # daily instead of weekly - costs nothing when nothing changed push: branches: [main] workflow_dispatch: inputs: force: description: "Build even if no upstream change was detected" type: boolean default: false env: IMAGE: ${{ vars.REGISTRY_HOST }}/ci-images/flutter-node FLUTTER_IMAGE: ghcr.io/cirruslabs/flutter:stable NODE_IMAGE: node:20-bookworm-slim jobs: check: runs-on: ubuntu-docker outputs: changed: ${{ steps.cmp.outputs.changed }} hash: ${{ steps.hash.outputs.hash }} flutter: ${{ steps.up.outputs.flutter }} node: ${{ steps.up.outputs.node }} date: ${{ steps.date.outputs.date }} steps: - name: Validate registry token run: test -n "${{ secrets.REGISTRY_TOKEN }}" || { echo "REGISTRY_TOKEN missing"; exit 1; } - name: Checkout uses: actions/checkout@v4 - name: Set up Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Gitea registry uses: docker/login-action@v3 with: registry: ${{ vars.REGISTRY_HOST }} username: ${{ github.actor }} password: ${{ secrets.REGISTRY_TOKEN }} # Resolve the mutable upstream tags to immutable digests, right now. - name: Resolve upstream digests id: up run: | set -euo pipefail f=$(docker buildx imagetools inspect "$FLUTTER_IMAGE" --format '{{.Manifest.Digest}}') n=$(docker buildx imagetools inspect "$NODE_IMAGE" --format '{{.Manifest.Digest}}') echo "flutter=$f" >> "$GITHUB_OUTPUT" echo "node=$n" >> "$GITHUB_OUTPUT" echo "flutter: $f" echo "node: $n" - name: Compute input hash id: hash run: | set -euo pipefail h=$(printf '%s\n' \ "${{ steps.up.outputs.flutter }}" \ "${{ steps.up.outputs.node }}" \ "$(sha256sum Dockerfile | cut -d' ' -f1)" \ | sha256sum | cut -c1-12) echo "hash=$h" >> "$GITHUB_OUTPUT" echo "input hash: $h" # The whole gate: does a marker tag for this exact input set already exist? - name: Compare against what is already published id: cmp run: | set -euo pipefail if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event.inputs.force }}" = "true" ]; then echo "changed=true" >> "$GITHUB_OUTPUT" echo "non-scheduled or forced run - building" exit 0 fi if docker buildx imagetools inspect "$IMAGE:src-${{ steps.hash.outputs.hash }}" >/dev/null 2>&1; then echo "changed=false" >> "$GITHUB_OUTPUT" echo "no change since last build - skipping" else echo "changed=true" >> "$GITHUB_OUTPUT" echo "upstream or Dockerfile changed - building" fi - name: Compute date tag id: date run: echo "date=$(date -u +%Y%m%d)" >> "$GITHUB_OUTPUT" build: needs: check if: needs.check.outputs.changed == 'true' runs-on: ubuntu-docker steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Gitea registry uses: docker/login-action@v3 with: registry: ${{ vars.REGISTRY_HOST }} username: ${{ github.actor }} password: ${{ secrets.REGISTRY_TOKEN }} - name: Build and push uses: docker/build-push-action@v5 with: context: . push: true pull: true # re-resolve bases; without this the cron is a no-op provenance: false # no attestation manifest -> half the package versions cache-from: type=registry,ref=${{ env.IMAGE }}:stable cache-to: type=inline build-args: | IMAGE_SOURCE=https://${{ vars.REGISTRY_HOST }}/ci-images/flutter-node FLUTTER_IMAGE=${{ env.FLUTTER_IMAGE }}@${{ needs.check.outputs.flutter }} NODE_IMAGE=${{ env.NODE_IMAGE }}@${{ needs.check.outputs.node }} labels: | org.opencontainers.image.base.name=${{ env.FLUTTER_IMAGE }} org.opencontainers.image.base.digest=${{ needs.check.outputs.flutter }} org.opencontainers.image.revision=${{ github.sha }} tags: | ${{ env.IMAGE }}:stable ${{ env.IMAGE }}:${{ needs.check.outputs.date }} ${{ env.IMAGE }}:src-${{ needs.check.outputs.hash }}