Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
aa1b309
docs: trivial change to readme
bosbaber Feb 9, 2026
f8dc861
chore: trivial experimental change
Feb 13, 2026
4c58b2f
Merge branch 'main' into staging
bosbaber Feb 20, 2026
8843068
Merge remote-tracking branch 'origin/main' into staging
Feb 20, 2026
8d0b868
ci: CMS changes to merge will now cause strapi rebuild (#47)
bosbaber Feb 20, 2026
e2ee59e
ci: trivial change to trigger cms build (#48)
bosbaber Feb 20, 2026
9a8ae76
ci: better reloadign of bashrc (#49)
bosbaber Feb 20, 2026
ea1d146
ci: changed pipeline structure (#50)
bosbaber Feb 20, 2026
2a7e103
ci: merged ci scripts and triggered rebuild (#51)
bosbaber Feb 20, 2026
869503d
ci: use pnpm to run sync script (#52)
bosbaber Feb 20, 2026
3602d5e
ci: trivial changes to test (#53)
bosbaber Feb 20, 2026
addc1b0
ci: trigger another test (#54)
bosbaber Feb 20, 2026
80f7323
ci: trigger another test (#55)
bosbaber Feb 20, 2026
ad0727b
fix: merge detection issue (#56)
bosbaber Feb 20, 2026
1259bef
ci: pipeline test (#57)
bosbaber Feb 20, 2026
8c51907
fix: add packages field to cms workspace yaml (#58)
bosbaber Feb 20, 2026
310bb92
test: workflow changes (#59)
bosbaber Feb 20, 2026
02a7fc4
fix: should be able to do mdx sync on staging as well (#60)
bosbaber Feb 20, 2026
5a2545f
ci: test mdx change (#61)
bosbaber Feb 20, 2026
44b1204
fix: improve pr detection (#62)
bosbaber Feb 20, 2026
3e953ee
ci: trigger (#63)
bosbaber Feb 20, 2026
6ad6319
fix: restrict manual workflow dispatch to staging branch only (#64)
bosbaber Feb 20, 2026
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
24 changes: 16 additions & 8 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Ensure these are installed before running any commands:

### CI Validation Pipeline

The GitHub Actions workflow (`.github/workflows/test-build.yml`) runs on every PR:
The GitHub Actions workflow (`.github/workflows/lint.yml`) runs on every PR and push to main:
1. Checkout code
2. Setup Node.js (v18)
3. Setup pnpm
Expand All @@ -41,6 +41,8 @@ The GitHub Actions workflow (`.github/workflows/test-build.yml`) runs on every P

**To replicate CI locally**: Run `pnpm install && pnpm run lint && pnpm run build`. Both lint and build must pass with no output errors.

**Note**: CI uses npm for installation despite Bun being the preferred local package manager. This is intentional for CI consistency.

### Important Caveats

- **Node Version**: The system may have multiple Node versions. If build fails with "Node.js vX.X.X is not supported by Astro", upgrade to >=18.20.8. The .nvmrc specifies `lts/iron` (Node 20), which is recommended.
Expand Down Expand Up @@ -98,7 +100,7 @@ The GitHub Actions workflow (`.github/workflows/test-build.yml`) runs on every P

## Content and Routing

- **Main navigation**: Configured in `src/config/navigation.json`
- **Foundation navigation**: Configured in `src/config/foundation-navigation.json`
- **Summit navigation**: Configured in `src/config/summit-navigation.json`
- **Dynamic routing**: `src/pages/[...page].astro` handles catch-all routes
- **Blog routing**: `src/pages/blog/[...page].astro` and `src/pages/developers/blog/[...page].astro` for dated blog content
Expand All @@ -109,6 +111,7 @@ The GitHub Actions workflow (`.github/workflows/test-build.yml`) runs on every P
- **Branches**: `staging` is the preview environment, `main` is production.
- **Strapi publishing**: Lifecycle hooks generate MDX and commit/push to `staging`.
- **Netlify**: Auto-builds `staging` to preview and `main` to production.
- **Self-hosted runner**: The `.github/workflows/main-merge.yml` runs on push to `staging` via a self-hosted runner (`strapi-vm`). It automatically rebuilds Strapi CMS if cms/ directory changes are detected, using `bun install && bun run build`.
- **Promotion**: Content moves from `staging` to `main` via PR approval.
- **Preview drafts**: Drafts can be previewed via SSR without publishing.

Expand All @@ -126,7 +129,7 @@ The GitHub Actions workflow (`.github/workflows/test-build.yml`) runs on every P

1. **ESLint warnings in CMS**: The file `cms/src/api/page/content-types/page/lifecycles.ts` contains warnings about unused variables and `any` types. These exist in the repo and are pre-existing. They do not block the build but do prevent `pnpm run lint` from passing.

2. **Node version mismatch in CI**: The GitHub Actions workflow uses Node 18, but newer patch versions (>=18.20.8) are required. The workflow's `actions/setup-node@v3` should install a compatible patch version automatically.
2. **Translation structure commented out**: `src/config` in astro.config.mjs has an i18n config block commented with TODO. Do not enable without understanding the full routing implications.

3. **Translation structure commented out**: `src/config` in astro.config.mjs has an i18n config block commented with TODO. Do not enable without understanding the full routing implications.

Expand All @@ -136,17 +139,23 @@ The GitHub Actions workflow (`.github/workflows/test-build.yml`) runs on every P

The CMS (Strapi v5.31.3) runs independently and uses **pnpm**:
```bash
# Local development (uses npm)
cd cms
pnpm install
pnpm run develop # Runs on localhost:1337/admin
pnpm run build # Production build
```

Content published in the CMS automatically generates MDX files in `src/content/foundation-pages/` via lifecycle hooks. MDX generation is handled by `cms/scripts/sync-mdx.cjs`.
**Production builds** (self-hosted runner on `staging` push):
- Uses `bun install && bun run build` via `.github/workflows/main-merge.yml`
- Includes `NODE_OPTIONS="--max-old-space-size=4096"` to handle OOM errors during build
- Automatically restarts the `strapi.service` after rebuild

Content published in the CMS automatically generates MDX files in `src/content/foundation-pages/` via lifecycle hooks. MDX generation is handled by `cms/scripts/sync-mdx/index.ts`.

For pages and blog posts, those lifecycle hooks also run a git add/commit/pull --rebase/push to trigger preview builds. Grant tracks only write/delete MDX locally. Set `STRAPI_DISABLE_GIT_SYNC=true` to disable the git sync.
For pages and blog posts, lifecycle hooks may trigger git synchronization for preview builds. Set `STRAPI_DISABLE_GIT_SYNC=true` to disable the git sync.

CMS code changes are deployed to the Strapi VM when merged to `staging`. Content-only changes can be rebuilt into Strapi via `cms/scripts/sync-mdx.cjs`.
CMS code changes are deployed to the Strapi VM when merged to `staging`. The self-hosted runner will automatically rebuild if `cms/` directory changes are detected.

## Making Changes

Expand All @@ -158,7 +167,7 @@ When making changes to Astro components, pages, or styles:
5. If format fails due to ESLint warnings, address warnings manually (check files listed in format output)
6. Verify `pnpm run build` succeeds (no output errors)

For content changes (MDX files), they are hot-reloaded during dev. For navigation changes, edit `src/config/navigation.json` and verify the sidebar updates correctly.
For content changes (MDX files), they are hot-reloaded during dev. For navigation changes, edit `src/config/foundation-navigation.json` or `src/config/summit-navigation.json` and verify the sidebar updates correctly.

## Files to Avoid Modifying

Expand All @@ -167,7 +176,6 @@ These files are auto-generated or have special constraints and should not be man
- `cms/src/index.ts` – Generated by Strapi plugin (in eslint ignore list)
- `cms/src/admin/app.tsx` – Generated by Strapi (in eslint ignore list)
- `public/scripts/highlight.min.js` – Minified third-party library
- `src/pages/financial-services.astro` – In eslint ignore list (pre-existing issues)
- `.astro/` directory – Build cache

## Trust These Instructions
Expand Down
68 changes: 0 additions & 68 deletions .github/workflows/main-merge.yml

This file was deleted.

197 changes: 197 additions & 0 deletions .github/workflows/staging-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
name: Staging Merge Workflow

on:
# Run when PRs are merged to staging
# WARNING: Do not trigger on pull_request events. We do not want forks to run code on our self-hosted runner,
# and pull_request events run for forks. This workflow should only run on push to staging.
push:
branches:
- staging

# Manual trigger for sync operations from any branch
workflow_dispatch:

concurrency:
# Ensure only one instance of this workflow runs at a time to avoid conflicts
group: staging-merge
cancel-in-progress: false

jobs:
check-pr-merge:
runs-on: ubuntu-latest
outputs:
is_merged_pr: ${{ steps.pr_merge_check.outputs.merged_pr }}
cms_changed: ${{ steps.detect_changes.outputs.cms_changed }}
content_changed: ${{ steps.detect_changes.outputs.content_changed }}

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Validate manual trigger is on staging branch
if: github.event_name == 'workflow_dispatch'
shell: bash
run: |
set -euo pipefail

CURRENT_BRANCH="${GITHUB_REF##*/}"
if [ "$CURRENT_BRANCH" != "staging" ]; then
echo "❌ Error: Manual workflow dispatch is only allowed on 'staging' branch"
echo " Current branch: $CURRENT_BRANCH"
exit 1
fi
echo "✓ Manual trigger validated on staging branch"

- name: Check if push is from merged PR
id: pr_merge_check
uses: actions/github-script@v7
with:
script: |
// Skip PR check for manual dispatch
if (context.eventName === 'workflow_dispatch') {
core.setOutput('merged_pr', 'manual')
core.notice('Manually triggered workflow; PR check skipped.')
return
}

const owner = context.repo.owner
const repo = context.repo.repo
const sha = context.sha

// Check via API for associated PRs merged into staging
const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
owner,
repo,
commit_sha: sha,
per_page: 100
})

const mergedPRIntoStaging = prs.some((pr) =>
pr.merged_at && pr.base && pr.base.ref === 'staging'
)

// Also check commit message for merge commit pattern
const { data: commit } = await github.rest.repos.getCommit({
owner,
repo,
ref: sha
})

const isMergeCommit = commit.commit.message.match(/^Merge pull request #(\d+)/) &&
commit.parents.length > 1

const mergedIntoStaging = mergedPRIntoStaging || isMergeCommit

core.setOutput('merged_pr', mergedIntoStaging ? 'true' : 'false')
if (!mergedIntoStaging) {
core.notice('No merged PR into staging found for this commit; workflow steps will be skipped.')
} else {
core.notice('Merged PR detected into staging.')
}

- name: Detect changed paths
id: detect_changes
if: steps.pr_merge_check.outputs.merged_pr != 'false'
shell: bash
run: |
set -euo pipefail

cms_changed=false
content_changed=false

# For manual dispatch, always rebuild CMS and sync content
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "Manual trigger - will rebuild CMS and sync content"
cms_changed=true
content_changed=true
else
# Check what changed in this push
changed_files=$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}")

if echo "$changed_files" | grep -q '^cms/'; then
cms_changed=true
echo "CMS changes detected"
fi

if echo "$changed_files" | grep -qE '^src/content/(blog|events)/.*\.mdx$'; then
content_changed=true
echo "Content changes detected"
fi
fi

echo "cms_changed=$cms_changed" >> "$GITHUB_OUTPUT"
echo "content_changed=$content_changed" >> "$GITHUB_OUTPUT"

rebuild-strapi:
needs: check-pr-merge
if: |
(needs.check-pr-merge.outputs.is_merged_pr == 'true' && needs.check-pr-merge.outputs.cms_changed == 'true') ||
needs.check-pr-merge.outputs.is_merged_pr == 'manual'
runs-on: strapi-vm

steps:
- name: Rebuild Strapi CMS
shell: bash
run: |
set -euo pipefail

# Add pnpm to PATH (not loaded from .bashrc in GitHub Actions)
export PNPM_HOME="/home/strapi/.local/share/pnpm"
export PATH="$PNPM_HOME:$PATH"

cd /home/strapi/interledger.org-v5-staging

# Ensure pull fails instead of creating merge commits
git fetch
git pull --ff-only

# Defensive check: fail if git index contains unresolved conflicts
if [ -n "$(git ls-files -u)" ]; then
echo "Unresolved git conflicts detected after pull"
exit 1
fi

cd /home/strapi/interledger.org-v5-staging/cms
# Stop the service while we rebuild
sudo systemctl stop strapi.service
# Install dependencies in case there are new ones from the merged PRs
pnpm install
# Rebuild with more memory to avoid OOM errors during build
NODE_OPTIONS="--max-old-space-size=4096" pnpm run build
sudo systemctl start strapi.service
sleep 5
sudo systemctl status strapi.service

sync-mdx-to-strapi:
needs: [check-pr-merge, rebuild-strapi]
if: |
always() &&
((needs.check-pr-merge.outputs.is_merged_pr == 'true' && needs.check-pr-merge.outputs.content_changed == 'true') ||
needs.check-pr-merge.outputs.is_merged_pr == 'manual')
runs-on: ubuntu-latest

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9

- name: Install dependencies
run: pnpm install

- name: Sync MDX to Strapi
working-directory: cms
env:
STRAPI_URL: ${{ secrets.STRAPI_URL }}
STRAPI_API_TOKEN: ${{ secrets.STRAPI_API_TOKEN }}
run: pnpm run sync:mdx
32 changes: 0 additions & 32 deletions .github/workflows/sync-mdx-to-strapi.yml

This file was deleted.

2 changes: 2 additions & 0 deletions cms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This is the Strapi CMS for managing content that will be rendered on the Interledger Developers Portal. The CMS automatically generates MDX files that are read by the Astro site.

<!-- Test workflow run -->

## Features

- **Automatic MDX Generation**: Content is automatically written to MDX files when published
Expand Down
Loading
Loading