Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and publish a Docker image to ghcr.io | |
| # Every push to main is built, smoke-tested and pushed as `main` but `latest` moves only when a release is published | |
| on: | |
| push: | |
| branches: | |
| - main | |
| release: | |
| types: | |
| - published | |
| jobs: | |
| check: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-node@v5 | |
| with: | |
| # The version the image is built on, so a failure here is one the image would hit | |
| node-version: 26.7.0 | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run lint | |
| - run: npm run check | |
| - run: npm test | |
| docker_publish: | |
| # Nothing is published from a red main | |
| needs: check | |
| runs-on: ubuntu-latest | |
| # GITHUB_TOKEN is read-only by default; pushing to ghcr.io needs the package scope | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Log in to ghcr.io | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| # ghcr.io rejects uppercase image names, and the repository owner has one | |
| - id: image | |
| env: | |
| REPOSITORY: ${{ github.repository }} | |
| RELEASE_TAG: ${{ github.event.release.tag_name }} | |
| run: | | |
| name="ghcr.io/${REPOSITORY,,}" | |
| if [ "$GITHUB_EVENT_NAME" = release ]; then | |
| tags="$name:latest,$name:$RELEASE_TAG" | |
| else | |
| tags="$name:main,$name:$GITHUB_SHA" | |
| fi | |
| echo "tags=$tags" >> "$GITHUB_OUTPUT" | |
| # Loaded into the local daemon first so the image is exercised before it is published; | |
| # the publish below reuses these layers from the cache | |
| - name: Build a Docker image for ${{ github.repository }} | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| load: true | |
| tags: glass-garden:smoke | |
| # The image carries no node_modules, so a runtime dependency that failed to bundle | |
| # shows up here as a container that dies on startup rather than as a red page for | |
| # whoever pulls it. Cross-origin isolation is checked too: without those headers the | |
| # app has no SharedArrayBuffer and cannot boot its VM | |
| - name: The image starts and serves a cross-origin-isolated page | |
| run: | | |
| docker run --detach --name smoke --publish 3000:3000 glass-garden:smoke | |
| for _ in $(seq 30); do | |
| curl --silent --fail --output /dev/null http://localhost:3000/ && break | |
| sleep 1 | |
| done | |
| docker logs smoke | |
| curl --silent --fail --dump-header - --output /dev/null http://localhost:3000/ \ | |
| | grep --ignore-case --quiet 'cross-origin-embedder-policy: require-corp' | |
| - name: Publish the image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| push: true | |
| # Keeps the package page to real architectures rather than an unknown/unknown entry | |
| provenance: false | |
| tags: ${{ steps.image.outputs.tags }} |