diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 49a07af..ab5fc0e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,7 +1,17 @@ name: Build on: - push: {} + # Only main. This used to be `push: {}` — every branch, every push — so a + # work-in-progress branch would build and publish an image. A push here + # means OUR packaging changed, which is a legitimate reason to rebuild; + # a push to a feature branch is not. + push: + branches: [main] + # PRs BUILD but do not PUSH (see the bake step). Restricting this workflow + # to main alone removed all pre-merge validation: a broken build would + # then only surface after merging, which is how this one went unnoticed + # for two weeks in the first place. + pull_request: workflow_dispatch: inputs: repo: @@ -18,15 +28,22 @@ on: options: - release - pre-release - - master # ref: # description: 'Obico Commit' # default: 'HEAD' # required: true env: - OBICO_REPO: ${{ inputs.repo }} - OBICO_BRANCH: ${{ inputs.branch }} + # `inputs.*` is populated ONLY for workflow_dispatch. On a push event both + # are the empty string, and actions/checkout with repository:'' silently + # checks out THIS repo instead of obico-server — so ./obico became a copy + # of obico-docker, and `mv frontend backend/` failed on a directory that + # was never going to be there. + # + # Every push run had failed since 2026-07-31 (12 of 12); 4 of 5 dispatch + # runs succeeded. The defaults make both paths behave the same. + OBICO_REPO: ${{ inputs.repo || 'TheSpaghettiDetective/obico-server' }} + OBICO_BRANCH: ${{ inputs.branch || 'release' }} jobs: build-images: @@ -52,6 +69,40 @@ jobs: registry: ghcr.io username: ${{ github.actor }} password: ${{ github.token }} + # Upstream owns this layout and has never promised it. When it moves, + # the old failure was `mv: cannot stat 'frontend'` — which says + # nothing about which repo, which ref, or what IS there. This asserts + # the shape first and prints the actual tree on failure, so a layout + # change is diagnosed in one look instead of a bisect. + # Only release and pre-release are buildable. `master` is upstream's + # development trunk: it builds, it publishes, and what comes out is + # whatever happened to be mid-flight that day — indistinguishable + # afterwards from a real release image. It was in the dispatch menu, + # one mis-click away. + - name: Refuse to build from a non-release ref + run: | + case "${OBICO_BRANCH}" in + release|pre-release) echo "building from ${OBICO_BRANCH}" ;; + *) + echo "::error::refusing to build from '${OBICO_BRANCH}' — only release or pre-release" + exit 1 ;; + esac + + - name: Verify upstream layout before assembling + run: | + missing="" + for d in frontend backend; do + [ -d "obico/$d" ] || missing="$missing $d" + done + if [ -n "$missing" ]; then + echo "::error::${OBICO_REPO}@${OBICO_BRANCH} is missing:${missing}" + echo "Top level of the checkout was:" + ls -1 obico | sed 's/^/ /' + echo "If upstream reorganised, update this step and the assembly below." + exit 1 + fi + echo "layout ok: obico/frontend and obico/backend present" + - name: Update compose file run: | cp -r obico/* . @@ -64,7 +115,11 @@ jobs: uses: docker/bake-action@v7 with: files: "bake.hcl,docker-compose.yml" - push: true + # Publish only from main or a deliberate dispatch. A PR proves the + # image BUILDS; it has no business publishing one, and an image + # from an unmerged branch is indistinguishable afterwards from a + # real release. + push: ${{ github.event_name != 'pull_request' }} source: . # - name: Docker meta # id: meta