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
67 changes: 64 additions & 3 deletions .github/workflows/build-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,30 @@ on:
- main
- releases
- 'pr-releases/**'
# Dependency-bump branches are the one place third-party code
# enters this repo, and the `publish` job below holds a
# `contents: write` token. Keep the two apart.
- 'dependabot/**'
delete:

permissions: write-all
# Least privilege: each job opts in to only the scopes it needs.
permissions: {}

jobs:
build:
# Only run on push events (not delete)
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
# No token left in .git/config: this job runs third-party
# build tooling and must not carry push credentials.
persist-credentials: false

- name: Use Node.js
uses: actions/setup-node@v6
Expand All @@ -35,18 +46,66 @@ jobs:
special-pages/node_modules
messaging/node_modules
types-generator/node_modules
key: ${{ runner.os }}-node-modules-${{ hashFiles('.nvmrc') }}-${{ hashFiles('**/package-lock.json') }}
key: ${{ runner.os }}-node-modules-noscripts-${{ hashFiles('.nvmrc') }}-${{ hashFiles('**/package-lock.json') }}

- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci
# --ignore-scripts blocks dependency lifecycle hooks. Only three
# packages in the tree declare one: `injected` (ours, re-run
# below), `esbuild` (resolves its platform binary at runtime) and
# `fsevents` (macOS-only, optional).
run: npm ci --ignore-scripts

- name: Generate SJCL bundle
if: steps.cache-node-modules.outputs.cache-hit != 'true'
# Normally injected's postinstall; run explicitly since the
# install above skips scripts.
run: npm run copy-sjcl -w injected

- name: Run build
run: npm run build

- name: Build docs preview
run: npm run docs-preview

- name: Package build output
# Tar rather than hand upload-artifact three paths: it pins the
# layout (upload-artifact roots the archive at the common
# ancestor of whatever actually matched, which shifts if a path
# comes up empty) and turns ~2.5k small files into one blob.
run: tar -czf build-output.tar.gz build Sources/ContentScopeScripts/dist docs

- name: Upload build output
uses: actions/upload-artifact@v7
with:
name: build-output
path: build-output.tar.gz
# Handoff to `publish` only; no reason to retain it.
retention-days: 1

publish:
# Split from `build` so the token that can write to this repo never
# shares a runner with third-party build tooling.
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
Comment thread
jonathanKingston marked this conversation as resolved.

steps:
- name: Checkout repository
uses: actions/checkout@v7

- name: Download build output
uses: actions/download-artifact@v8
with:
name: build-output

- name: Unpack build output
run: |
tar -xzf build-output.tar.gz
rm build-output.tar.gz

- name: Create and push build branch
id: create_branch
env:
Expand Down Expand Up @@ -236,6 +295,8 @@ jobs:
# Only run when a branch is deleted, and only for non-pr-releases branches
if: github.event_name == 'delete' && github.event.ref_type == 'branch' && !startsWith(github.event.ref, 'pr-releases/')
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v7
Expand Down
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Built artifacts live on dedicated branches:
| Branch | Purpose | How it's created |
|--------|---------|-----------------|
| `releases` | Production releases. Tags (e.g. `12.38.0`) point here. | Manual `workflow_dispatch` on `build.yml` |
| `pr-releases/<branch>` | Per-PR build artifacts for cross-repo testing. | Automatic via `build-pr.yml` on every PR push |
| `pr-releases/<branch>` | Per-PR build artifacts for cross-repo testing. | Automatic via `build-branch.yml` on every PR push |

The `releases` branch is the long-lived equivalent of "what `main` would look like if we checked in build output". The `pr-releases/` branches are ephemeral — created when a PR is opened/updated, deleted when it's closed.

Expand All @@ -136,7 +136,7 @@ The workflow creates a tag and GitHub release automatically. Build artifacts on

### PR build branches

When you push to any branch (except `main`, `releases`, or `pr-releases/*`), the `build-pr.yml` workflow automatically:
When you push to any branch (except `main`, `releases`, `pr-releases/*`, or `dependabot/*`), the `build-branch.yml` workflow automatically:

1. Builds all workspaces (`npm run build`)
2. Pushes the source + build artifacts to `pr-releases/<your-branch-name>`
Expand All @@ -146,6 +146,8 @@ When you push to any branch (except `main`, `releases`, or `pr-releases/*`), the

The build branch is created on the first push and updated on every subsequent push. It's deleted automatically when the source branch is deleted.

Dependabot branches are deliberately excluded: the workflow's publish job holds a `contents: write` token, and dependency-bump branches are the one place third-party code enters the repo. Test a Dependabot bump via the regular CI checks or a local build instead.

**Using a PR build branch in a native client:**

```sh
Expand Down
Loading