Chore: sync fork with upstream main (2026-06-18)#1539
Conversation
|
|
Opened against upstream by mistake while preparing a fork sync PR; closing and recreating against the fork only. |
There was a problem hiding this comment.
Pull request overview
This PR refreshes the fork onto upstream emdash-cms/emdash main while preserving fork-specific “canonical repo only” workflow guards and local agent/dev metadata files.
Changes:
- Add an agent-facing warning to check
upstream/mainbefore doing substantive work on a fork. - Add
.nvmrcto pin a local Node version. - Gate several GitHub Actions workflows so release/preview/auto-format/auto-extract/CLA enforcement behavior is skipped outside
emdash-cms/emdash, and avoid CodeQL failures on fork sync PRs.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
AGENTS.md |
Adds fork workflow guidance to reduce drift-related mistakes. |
.nvmrc |
Pins a local Node version for this fork. |
.github/workflows/release.yml |
Adds canonical-repo/secret presence gating to release automation steps and template sync. |
.github/workflows/preview-releases.yml |
Skips preview publishing outside the canonical repo. |
.github/workflows/codeql.yml |
Skips CodeQL analysis on fork sync PRs to avoid failing on upstream alert backlog. |
.github/workflows/cla.yml |
Skips CLA enforcement/labeling outside the canonical repo. |
.github/workflows/auto-format.yml |
Adds canonical-repo/secret presence gating before formatting automation runs/pushes back. |
.github/workflows/auto-extract.yml |
Adds canonical-repo/secret presence gating before locale extraction automation runs/pushes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - name: Create Release Pull Request or Publish | ||
| if: ${{ !inputs.publish-only }} | ||
| if: ${{ steps.config.outputs.enabled == 'true' && !inputs.publish-only }} | ||
| id: changesets |
| - name: Publish (manual) | ||
| if: ${{ inputs.publish-only }} | ||
| if: ${{ steps.config.outputs.enabled == 'true' && inputs.publish-only }} | ||
| run: node .github/scripts/release.mjs publish |
| if: >- | ||
| needs.release.outputs.published == 'true' || | ||
| inputs.publish-only | ||
| github.repository == 'emdash-cms/emdash' && | ||
| (needs.release.outputs.published == 'true' || inputs.publish-only) | ||
| permissions: |
There was a problem hiding this comment.
Approach
This is a fork-sync PR (sync/upstream-main-2026-06-18) opened against upstream emdash-cms/emdash:main, even though the description frames it as refreshing richardjoo/emdash. The substantive part — adding github.repository != 'emdash-cms/emdash' skip guards to six workflows — is a legitimate, well-executed fork-friendliness improvement: every guard is a strict no-op on the canonical repo (where github.repository is always emdash-cms/emdash) and only activates on forks, where it gracefully skips automation that needs the APP_ID/APP_PRIVATE_KEY app secrets or pkg.pr.new. That part I'd take. The thing to consciously decide is the two fork-specific artifacts bundled in: a pinned .nvmrc that nothing in the repo consumes, and an AGENTS.md note tuned to fork maintainers (git fetch upstream). Those read as fork-local convenience rather than upstream maintenance, and are worth a maintainer's explicit yes/no rather than being accepted as part of a "sync."
What I checked
All six changed workflows, traced on the canonical-repo path (every guard passes through unchanged) and the fork-skip path (every working step is guarded by steps.config.outputs.enabled == 'true' or github.repository == 'emdash-cms/emdash'; on a fork only an echo runs — I confirmed no step is left unguarded that would fail without the app secrets). Required-check impact: codeql's "Require code scanning results" still uploads an empty SARIF on skipped runs; cla and auto-format run normally on upstream PRs. Checked cla.yml against its merge_group trigger (no null-deref on github.event.issue.pull_request), codeql.yml's revised decide logic (push/schedule still analyze; only fork PRs skip), and release.yml's sync-templates if (unchanged on upstream, skipped on forks). Confirmed YAML / if expression syntax and the ${{ }}-vs-bare-expression usage.
Conclusion
The implementation is clean — no behavior change on emdash-cms/emdash, no regressions, no security issue, and no changeset is needed (no published package is touched). Two minor suggestions below.
Scope note: the guards cover 6 of ~28 workflows. Other secret-using automation (investigate, bonk, maintainer-reply, reporter-reply, …) is still unguarded, so the "fork-friendly" goal is only partially met — fine if that's the intended scope, worth flagging if full coverage was the aim.
| env: | ||
| APP_ID: ${{ secrets.APP_ID }} | ||
| APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} | ||
| run: | | ||
| if [ "${{ github.repository }}" != "emdash-cms/emdash" ]; then |
There was a problem hiding this comment.
[suggestion] The config step interpolates ${{ github.repository }} directly into the run: script. github.repository is GitHub-controlled (owner/name), so this isn't a script-injection vector, but the same PR's codeql.yml change passes the value through env: REPOSITORY: and references $REPOSITORY (lines 79/82) — the recommended hardening pattern. For consistency within this PR, do the same here, and in auto-format.yml:25 and release.yml:40, which have the identical construct.
| env: | |
| APP_ID: ${{ secrets.APP_ID }} | |
| APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} | |
| run: | | |
| if [ "${{ github.repository }}" != "emdash-cms/emdash" ]; then | |
| env: | |
| APP_ID: ${{ secrets.APP_ID }} | |
| APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} | |
| REPOSITORY: ${{ github.repository }} | |
| run: | | |
| if [ "$REPOSITORY" != "emdash-cms/emdash" ]; then |
| @@ -0,0 +1 @@ | |||
| 22.22.2 | |||
There was a problem hiding this comment.
[suggestion] This adds a pinned Node 22.22.2. Nothing in the repo consumes .nvmrc — CI pins Node via floating node-version: 22 or node-version-file: package.json (against engines.node: ">=22"), and no workflow references .nvmrc. So on upstream the file is advisory-only and introduces a third source of truth for the Node version that diverges from the established convention. It reads as a fork-local convenience. If upstream doesn't want to maintain a pinned patch version, drop it from this PR; if it does, align it with the repo's node-version strategy rather than adding an unconsumed pin.
|
My apologies. Accidentally pushed PR to upstream instead of my forked repo. |
What does this PR do?
Refreshes
richardjoo/emdashonto currentemdash-cms/emdashmainwhile keeping only the fork-specific workflow guards plus local agent metadata (AGENTS.mdand.nvmrc).Closes #
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runmessages.pochanges except in translation PRs — a workflow extracts catalogs on merge tomain.AI-generated code disclosure
Screenshots / test output
Not run for this PR. This branch only replays the fork-specific workflow and metadata files on top of the latest upstream
main.