Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
name: Build & Publish Docker Image (Manual)
name: Build & Publish Docker Image

# Manual fallback for Docker publishing.
# Normally, Docker images are built automatically by the Release workflow.
# Use this workflow_dispatch if a release was created but the image wasn't published.
on:
# Automatic trigger when a release is published.
# NOTE: This only works when releases are created with a GitHub App token
# (not GITHUB_TOKEN). Until the App is configured, use workflow_dispatch.
release:
types: [published]

# Manual fallback for publishing when the release event doesn't fire.
workflow_dispatch:
inputs:
version:
Expand Down Expand Up @@ -32,6 +36,19 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Determine version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ inputs.version }}" >> "$GITHUB_OUTPUT"
else
# Extract version from release tag (e.g. scrolly-v1.2.0 -> 1.2.0, v1.2.0 -> 1.2.0)
TAG="${{ github.event.release.tag_name }}"
VERSION="${TAG#scrolly-v}"
VERSION="${VERSION#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
fi

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

Expand All @@ -51,7 +68,7 @@ jobs:
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=${{ inputs.version }}
type=raw,value=${{ steps.version.outputs.version }}
type=raw,value=latest

- name: Build and push
Expand All @@ -63,7 +80,7 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
APP_VERSION=${{ inputs.version }}
APP_VERSION=${{ steps.version.outputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max

Expand Down
153 changes: 15 additions & 138 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,154 +4,31 @@ on:
push:
branches: [main]

# TODO: Replace GITHUB_TOKEN with a GitHub App token to properly trigger
# CI/Security workflows on release-please PRs and docker-publish on releases.
# See: https://github.com/actions/create-github-app-token
#
# Once configured, add to this workflow:
# - name: Generate GitHub App token
# id: app-token
# uses: actions/create-github-app-token@v2
# with:
# app-id: ${{ vars.RELEASE_APP_ID }}
# private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
#
# Then pass `token: ${{ steps.app-token.outputs.token }}` to release-please.
# This eliminates all workarounds for GITHUB_TOKEN event limitations.

permissions:
contents: write
pull-requests: write
statuses: write
packages: write
security-events: write

jobs:
release-please:
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
version: ${{ steps.release.outputs.version }}
steps:
- name: Run release-please
id: release
uses: googleapis/release-please-action@v4
with:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json

# GITHUB_TOKEN-created PRs don't trigger CI workflows, so required
# status checks never run on the release branch. Since release-please
# only bumps versions and changelogs (code is already tested on main),
# we satisfy the required checks via the commit status API, then
# enable auto-merge so the PR merges once checks are satisfied.
- name: Auto-satisfy checks and enable auto-merge on release PR
if: steps.release.outputs.prs_created == 'true'
run: |
PR_NUMBER=$(gh pr list --label "autorelease: pending" --json number --jq '.[0].number')
if [ -z "$PR_NUMBER" ]; then
echo "No pending release PR found"
exit 0
fi
echo "Found release PR #$PR_NUMBER"
SHA=$(gh pr view "$PR_NUMBER" --json headRefOid --jq '.headRefOid')
for check in ci security-status; do
gh api "repos/${{ github.repository }}/statuses/$SHA" \
-f state=success \
-f context="$check" \
-f description="Release PR — code already tested on main"
done
gh pr merge "$PR_NUMBER" --squash --auto
env:
GH_TOKEN: ${{ github.token }}

# Run CodeQL on the release PR branch to satisfy the code scanning ruleset.
# GITHUB_TOKEN-created PRs don't trigger other workflows, so we run CodeQL
# here to ensure results are uploaded for the release PR commit.
codeql-release-pr:
needs: release-please
if: needs.release-please.outputs.release_created != 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Find release PR
id: find-pr
run: |
PR_NUMBER=$(gh pr list --label "autorelease: pending" --json number --jq '.[0].number')
if [ -z "$PR_NUMBER" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
REF=$(gh pr view "$PR_NUMBER" --json headRefName --jq '.headRefName')
echo "ref=$REF" >> "$GITHUB_OUTPUT"
echo "skip=false" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ github.token }}

- name: Checkout release PR branch
if: steps.find-pr.outputs.skip != 'true'
uses: actions/checkout@v4
with:
ref: ${{ steps.find-pr.outputs.ref }}

- name: Initialize CodeQL
if: steps.find-pr.outputs.skip != 'true'
uses: github/codeql-action/init@v3
with:
languages: javascript-typescript
config-file: .github/codeql/codeql-config.yml
queries: security-extended

- name: Autobuild
if: steps.find-pr.outputs.skip != 'true'
uses: github/codeql-action/autobuild@v3

- name: Perform CodeQL analysis
if: steps.find-pr.outputs.skip != 'true'
uses: github/codeql-action/analyze@v3
with:
category: '/language:javascript-typescript'

# Build and publish Docker image when a release is created.
# This runs in the same workflow to avoid the GITHUB_TOKEN limitation
# where release events created by GITHUB_TOKEN don't trigger other workflows.
docker:
needs: release-please
if: needs.release-please.outputs.release_created == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=${{ needs.release-please.outputs.version }}
type=raw,value=latest

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
APP_VERSION=${{ needs.release-please.outputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Set package visibility to public
run: |
curl -sf -X PATCH \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/orgs/312-dev/packages/container/scrolly" \
-d '{"visibility":"public"}' || true
Loading