From 1562cbda8e5df013a9922f6bd29c9db94a4e110b Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Tue, 28 Jul 2026 12:13:07 -0400 Subject: [PATCH 1/2] ci: scope the three reusable CI workflows to contents:read ci-python-sam, ci-typescript-cdk and ci-dotnet declared no permissions at any level, unlike every other workflow here. A reusable workflow that declares nothing inherits the CALLER's token scopes, and these are called from deploy repos, so a lint/test/synth job could run holding an OIDC-mintable token it has no use for. None of the three references GITHUB_TOKEN, github.token, gh, or any secret, so contents:read is all they need to check out and build. Also pass node-version explicitly in the cdk-deploy and ci-node templates. cicd.md requires callers to pin it so lockfileVersion 3 from local Node 24 / npm 11 cannot drift from the runner, but no template did. Only these two targets accept the input; sam-deploy, dotnet-eb, dependency-review and labeler do not, so they are left alone. Verified against all 22 callers across the org that none grants permissions omitting contents:read, so no repo's CI breaks on the caller-cannot-be-exceeded rule. --- .github/workflows/ci-dotnet.yaml | 3 +++ .github/workflows/ci-python-sam.yaml | 3 +++ .github/workflows/ci-typescript-cdk.yaml | 3 +++ workflow-templates/cdk-deploy.yml | 4 ++++ workflow-templates/ci-node.yml | 4 ++++ 5 files changed, 17 insertions(+) diff --git a/.github/workflows/ci-dotnet.yaml b/.github/workflows/ci-dotnet.yaml index b9c1a00..427a470 100644 --- a/.github/workflows/ci-dotnet.yaml +++ b/.github/workflows/ci-dotnet.yaml @@ -20,6 +20,9 @@ on: type: boolean default: true +permissions: + contents: read + jobs: ci: runs-on: ubuntu-latest diff --git a/.github/workflows/ci-python-sam.yaml b/.github/workflows/ci-python-sam.yaml index 95af16e..03b8df5 100644 --- a/.github/workflows/ci-python-sam.yaml +++ b/.github/workflows/ci-python-sam.yaml @@ -44,6 +44,9 @@ on: type: boolean default: true +permissions: + contents: read + jobs: ci: runs-on: ubuntu-latest diff --git a/.github/workflows/ci-typescript-cdk.yaml b/.github/workflows/ci-typescript-cdk.yaml index 0558f77..c239f2d 100644 --- a/.github/workflows/ci-typescript-cdk.yaml +++ b/.github/workflows/ci-typescript-cdk.yaml @@ -56,6 +56,9 @@ on: type: string default: "template.yaml" +permissions: + contents: read + jobs: ci: runs-on: ubuntu-latest diff --git a/workflow-templates/cdk-deploy.yml b/workflow-templates/cdk-deploy.yml index e39cacd..fb65cd3 100644 --- a/workflow-templates/cdk-deploy.yml +++ b/workflow-templates/cdk-deploy.yml @@ -6,5 +6,9 @@ on: jobs: deploy: uses: Sea-Haven-Industries/.github/.github/workflows/cd-cdk.yaml@555d07c3a240689a81668026787eba089df4c975 # main + with: + # Matches local dev (Node 24 / npm 11, lockfileVersion 3). This is also the + # reusable workflow's default — passed explicitly to pin against drift. + node-version: "24" secrets: deploy-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN }} diff --git a/workflow-templates/ci-node.yml b/workflow-templates/ci-node.yml index adca81b..c82818a 100644 --- a/workflow-templates/ci-node.yml +++ b/workflow-templates/ci-node.yml @@ -6,3 +6,7 @@ on: jobs: ci: uses: Sea-Haven-Industries/.github/.github/workflows/ci-typescript-cdk.yaml@555d07c3a240689a81668026787eba089df4c975 # main + with: + # Matches local dev (Node 24 / npm 11, lockfileVersion 3). This is also the + # reusable workflow's default — passed explicitly to pin against drift. + node-version: "24" From 8344efb90270c3bbc81c066570de77e47434c290 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Tue, 28 Jul 2026 12:34:29 -0400 Subject: [PATCH 2/2] ci: add starter workflows for the five uncovered reusables The workflow-templates catalog offered starter workflows for only 7 of the 12 reusable workflows in .github/workflows, so ci-python-app, ci-typescript-frontend, ci-static, ci-dotnet and cd-mobile-ios were invisible in the org's Actions > New workflow UI and had to be wired by hand. Add a template + properties.json pair for each. Each caller CI job is keyed `ci` so the check context resolves to the `ci / ci` required by the org ruleset, and every reusable ref is pinned to the same 40-char SHA the existing templates use. node-version: "24" is passed on the three reusables that declare the input (ci-typescript-frontend, ci-static, cd-mobile-ios); ci-python-app and ci-dotnet do not declare it, so it is omitted there. --- workflow-templates/ci-dotnet.properties.json | 7 +++++++ workflow-templates/ci-dotnet.yml | 14 +++++++++++++ .../ci-python-app.properties.json | 7 +++++++ workflow-templates/ci-python-app.yml | 14 +++++++++++++ workflow-templates/ci-static.properties.json | 7 +++++++ workflow-templates/ci-static.yml | 18 ++++++++++++++++ .../ci-typescript-frontend.properties.json | 7 +++++++ workflow-templates/ci-typescript-frontend.yml | 14 +++++++++++++ .../mobile-ios-deploy.properties.json | 7 +++++++ workflow-templates/mobile-ios-deploy.yml | 21 +++++++++++++++++++ 10 files changed, 116 insertions(+) create mode 100644 workflow-templates/ci-dotnet.properties.json create mode 100644 workflow-templates/ci-dotnet.yml create mode 100644 workflow-templates/ci-python-app.properties.json create mode 100644 workflow-templates/ci-python-app.yml create mode 100644 workflow-templates/ci-static.properties.json create mode 100644 workflow-templates/ci-static.yml create mode 100644 workflow-templates/ci-typescript-frontend.properties.json create mode 100644 workflow-templates/ci-typescript-frontend.yml create mode 100644 workflow-templates/mobile-ios-deploy.properties.json create mode 100644 workflow-templates/mobile-ios-deploy.yml diff --git a/workflow-templates/ci-dotnet.properties.json b/workflow-templates/ci-dotnet.properties.json new file mode 100644 index 0000000..26ceb8a --- /dev/null +++ b/workflow-templates/ci-dotnet.properties.json @@ -0,0 +1,7 @@ +{ + "name": "Sea Haven — CI (.NET)", + "description": "Runs dotnet restore, build (Release), and dotnet test for a solution or project via the org reusable workflow.", + "iconName": "octicon-checklist", + "categories": ["C#", "Continuous integration"], + "filePatterns": ["\\.csproj$", "\\.sln$"] +} diff --git a/workflow-templates/ci-dotnet.yml b/workflow-templates/ci-dotnet.yml new file mode 100644 index 0000000..29aace2 --- /dev/null +++ b/workflow-templates/ci-dotnet.yml @@ -0,0 +1,14 @@ +name: CI (.NET) +on: + pull_request: + branches: [main] + +jobs: + ci: + # Job id MUST stay `ci`: the reusable's job is also `ci`, so the check + # context resolves to the required `ci / ci`. + # + # Every input is optional. Common overrides: `solution` (defaults to *.sln + # in the working directory), `working-directory`, and `dotnet-version` + # (defaults to 8.0.x). This reusable has no `node-version` input. + uses: Sea-Haven-Industries/.github/.github/workflows/ci-dotnet.yaml@555d07c3a240689a81668026787eba089df4c975 # main diff --git a/workflow-templates/ci-python-app.properties.json b/workflow-templates/ci-python-app.properties.json new file mode 100644 index 0000000..b625e4e --- /dev/null +++ b/workflow-templates/ci-python-app.properties.json @@ -0,0 +1,7 @@ +{ + "name": "Sea Haven — CI (Python / app)", + "description": "Runs ruff check, ruff format --check, a pytest collect-only import check, and an optional subproject suite via the org reusable workflow. For Python repos that do not deploy via SAM or CDK.", + "iconName": "octicon-checklist", + "categories": ["Python", "Continuous integration"], + "filePatterns": ["requirements.*\\.txt$", "pyproject\\.toml$"] +} diff --git a/workflow-templates/ci-python-app.yml b/workflow-templates/ci-python-app.yml new file mode 100644 index 0000000..9e23b13 --- /dev/null +++ b/workflow-templates/ci-python-app.yml @@ -0,0 +1,14 @@ +name: CI (Python / app) +on: + pull_request: + branches: [main] + +jobs: + ci: + # Job id MUST stay `ci`: the reusable's aggregator job is also `ci`, so the + # check context resolves to the required `ci / ci`. + # + # Every input is optional. Common overrides: `source-dirs` (ruff targets), + # `requirements` (non-default requirements file), `subproject-dir` (a + # self-contained suite that must run in its own working directory). + uses: Sea-Haven-Industries/.github/.github/workflows/ci-python-app.yaml@555d07c3a240689a81668026787eba089df4c975 # main diff --git a/workflow-templates/ci-static.properties.json b/workflow-templates/ci-static.properties.json new file mode 100644 index 0000000..e22cb76 --- /dev/null +++ b/workflow-templates/ci-static.properties.json @@ -0,0 +1,7 @@ +{ + "name": "Sea Haven — CI (Static Site)", + "description": "Validates static HTML/CSS/JS sites (S3 + CloudFront repos): htmlhint, JSON-LD parsing, sitemap.xml well-formedness, and internal link resolution via the org reusable workflow.", + "iconName": "octicon-checklist", + "categories": ["HTML", "Continuous integration"], + "filePatterns": ["index\\.html$"] +} diff --git a/workflow-templates/ci-static.yml b/workflow-templates/ci-static.yml new file mode 100644 index 0000000..b7a1705 --- /dev/null +++ b/workflow-templates/ci-static.yml @@ -0,0 +1,18 @@ +name: CI (Static Site) +on: + pull_request: + branches: [main] + +jobs: + ci: + # Job id MUST stay `ci`: the reusable's job is also `ci`, so the check + # context resolves to the required `ci / ci`. + uses: Sea-Haven-Industries/.github/.github/workflows/ci-static.yaml@555d07c3a240689a81668026787eba089df4c975 # main + with: + # Pinned explicitly (handbook): local dev is Node 24 / npm 11, which + # generates lockfileVersion 3. Being explicit avoids lockfile drift. + node-version: "24" + # Defaults to source mode — the checks run against the repo root. For a + # templated site (Eleventy, Astro), add `build-command` plus `check-dir` + # so the checks validate the BUILT output that actually ships; otherwise + # they pass vacuously against source templates that contain no HTML. diff --git a/workflow-templates/ci-typescript-frontend.properties.json b/workflow-templates/ci-typescript-frontend.properties.json new file mode 100644 index 0000000..73d8113 --- /dev/null +++ b/workflow-templates/ci-typescript-frontend.properties.json @@ -0,0 +1,7 @@ +{ + "name": "Sea Haven — CI (TypeScript / frontend)", + "description": "Runs the Sea Haven standards gate, format:check, lint, build, unit tests, and a Playwright browser smoke for bundled Vite/React/Vue apps via the org reusable workflow.", + "iconName": "octicon-checklist", + "categories": ["TypeScript", "JavaScript", "Continuous integration"], + "filePatterns": ["package\\.json$", "vite\\.config\\.[jt]s$", "playwright\\.config\\.[jt]s$"] +} diff --git a/workflow-templates/ci-typescript-frontend.yml b/workflow-templates/ci-typescript-frontend.yml new file mode 100644 index 0000000..3b75187 --- /dev/null +++ b/workflow-templates/ci-typescript-frontend.yml @@ -0,0 +1,14 @@ +name: CI (TypeScript / frontend) +on: + pull_request: + branches: [main] + +jobs: + ci: + # Job id MUST stay `ci`: the reusable's job is also `ci`, so the check + # context resolves to the required `ci / ci`. + uses: Sea-Haven-Industries/.github/.github/workflows/ci-typescript-frontend.yaml@555d07c3a240689a81668026787eba089df4c975 # main + with: + # Pinned explicitly (handbook): local dev is Node 24 / npm 11, which + # generates lockfileVersion 3. Being explicit avoids lockfile drift. + node-version: "24" diff --git a/workflow-templates/mobile-ios-deploy.properties.json b/workflow-templates/mobile-ios-deploy.properties.json new file mode 100644 index 0000000..fea029e --- /dev/null +++ b/workflow-templates/mobile-ios-deploy.properties.json @@ -0,0 +1,7 @@ +{ + "name": "Sea Haven — Deploy (iOS / TestFlight)", + "description": "Builds the iOS app with Fastlane and uploads it to TestFlight on push to main, using the org reusable cd-mobile-ios workflow. Requires the AWS_DEPLOY_ROLE_ARN, MATCH_PASSWORD, ASC_KEY_ID, ASC_ISSUER_ID and ASC_KEY_CONTENT repo secrets.", + "iconName": "octicon-rocket", + "categories": ["Deployment", "Mobile", "JavaScript"], + "filePatterns": ["Gemfile$", "app\\.json$", "metro\\.config\\.[cm]?js$"] +} diff --git a/workflow-templates/mobile-ios-deploy.yml b/workflow-templates/mobile-ios-deploy.yml new file mode 100644 index 0000000..ece8fd5 --- /dev/null +++ b/workflow-templates/mobile-ios-deploy.yml @@ -0,0 +1,21 @@ +name: Deploy (iOS / TestFlight) +on: + push: + branches: [main] + +jobs: + deploy: + uses: Sea-Haven-Industries/.github/.github/workflows/cd-mobile-ios.yaml@555d07c3a240689a81668026787eba089df4c975 # main + with: + # Pinned explicitly (handbook): local dev is Node 24 / npm 11, which + # generates lockfileVersion 3. Being explicit avoids lockfile drift. + node-version: "24" + secrets: + # All five are required. deploy-role-arn is the repo's OIDC role, used + # here to read the fastlane match certificate store from S3; the four + # asc-*/match-* values come from App Store Connect and the match repo. + deploy-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN }} + match-password: ${{ secrets.MATCH_PASSWORD }} + asc-key-id: ${{ secrets.ASC_KEY_ID }} + asc-issuer-id: ${{ secrets.ASC_ISSUER_ID }} + asc-key-content: ${{ secrets.ASC_KEY_CONTENT }}