📦 deps(thirdparty): update snapshots
This commit is contained in:
+33
-30
@@ -5,7 +5,7 @@
|
||||
This guide details the exact procedures for maintaining `agentic-awesome-skills`.
|
||||
It covers the **Quality Bar**, **Documentation Consistency**, and **Release Workflows**.
|
||||
|
||||
**Maintainer shortcuts:** [Merge a PR](#b-when-you-merge-a-pr-step-by-step) · [Reopen & merge a closed PR](#if-a-pr-was-closed-after-local-integration-reopen-and-merge) · [Post-merge credits sync](#c-post-merge-credits-sync-mandatory-after-every-pr-merge) · [Close issues](#when-to-close-an-issue) · [Create a release](#4-release-workflow)
|
||||
**Maintainer shortcuts:** [Merge a PR](#b-when-you-merge-a-pr-step-by-step) · [Reopen & merge a closed PR](#if-a-pr-was-closed-after-local-integration-reopen-and-merge) · [Post-batch credits verification](#c-post-batch-credits-verification) · [Close issues](#when-to-close-an-issue) · [Create a release](#4-release-workflow)
|
||||
|
||||
---
|
||||
|
||||
@@ -39,7 +39,7 @@ If you touch **any of these**:
|
||||
…then you **MUST** run the Validation Chain **BEFORE** committing.
|
||||
|
||||
- Running `npm run chain` is **NOT optional**.
|
||||
- Running `npm run catalog` is **NOT optional**.
|
||||
- `npm run chain` already includes catalog generation; do not invoke `npm run catalog` again immediately afterward.
|
||||
|
||||
For contributor PRs, the contract is now **source-only**:
|
||||
|
||||
@@ -113,17 +113,11 @@ Before ANY commit that adds/modifies skills, run the chain:
|
||||
This verifies that changed skills with declared external upstream repos already have the required README credit under `### Official Sources` or `### Community Contributors`.
|
||||
The first rollout is warning-first for missing structured metadata: if a changed skill clearly looks externally sourced but still lacks `source_repo`, the check warns instead of failing. Once `source_repo` is declared, README coverage is mandatory.
|
||||
|
||||
4. **Build catalog**:
|
||||
|
||||
```bash
|
||||
npm run catalog
|
||||
```
|
||||
|
||||
5. **Optional maintainer sweep shortcut**:
|
||||
4. **Optional maintainer sweep shortcut**:
|
||||
```bash
|
||||
npm run sync:repo-state
|
||||
```
|
||||
This wraps `chain + catalog + sync:web-assets + sync:contributors + audit:consistency` for a full local repo-state refresh.
|
||||
This wraps `chain + sync:web-assets + sync:contributors + audit:consistency` for a full local repo-state refresh; `chain` already generates the catalog.
|
||||
The scheduled GitHub Actions workflow `Repo Hygiene` runs this same sweep weekly to catch slow drift on `main`.
|
||||
It also enforces the frozen validation warning budget, so new warnings do not creep in silently while the legacy `135` known warnings remain accepted.
|
||||
|
||||
@@ -139,10 +133,9 @@ Before ANY commit that adds/modifies skills, run the chain:
|
||||
```
|
||||
Risk labels are declared metadata. Validate the declared value and review ambiguous `risk: unknown` cases semantically; do not infer or rewrite risk from isolated words.
|
||||
|
||||
6. **PROVE GENERATED STATE, BUT KEEP SOURCE PRS SOURCE-ONLY**:
|
||||
5. **PROVE GENERATED STATE, BUT KEEP SOURCE PRS SOURCE-ONLY**:
|
||||
```bash
|
||||
npm run chain
|
||||
npm run catalog
|
||||
git status --short
|
||||
```
|
||||
> 🔴 **CRITICAL for maintainer pull requests**: Inspect the generated delta as validation, then exclude derived registries, plugin mirrors, marketplaces, and other generated outputs from the source PR. The protected `automation/canonical-repo-state` PR owns that state after source merge.
|
||||
@@ -165,6 +158,14 @@ For every canonical `SKILL.md` or tracked bundle-file change, run validation, re
|
||||
3. **Quality Bar** — PR description confirms the [Quality Bar Checklist](.github/PULL_REQUEST_TEMPLATE.md) (metadata, risk label, credits if applicable).
|
||||
4. **Issue link** — If the PR fixes an issue, the PR description should contain `Closes #N` or `Fixes #N` so GitHub auto-closes the issue on merge.
|
||||
|
||||
**Required-CI execution contract:**
|
||||
|
||||
- `pr-policy` executes the fork-safety intake with code materialized from the exact protected base before the dependent required jobs start. This is an early, unprivileged rejection of unsafe fork diffs; `merge:batch` still recomputes the trusted decision and remains the only fork-run approval and merge authority.
|
||||
- The reported `impact_profile` is shadow telemetry only. It does not skip, downgrade, or satisfy any required check.
|
||||
- For an ordinary source PR, `source-validation` performs the generated-state refresh once and publishes a manifest bound to the exact repository, workflow/run attempt, and PR head SHA. `artifact-preview` verifies that manifest and its digest; it does not regenerate the same source-PR tree.
|
||||
- For the protected canonical-sync PR, `pr-policy` reproduces the exact tree from trusted `main`, `source-validation` records a lightweight boundary, and `artifact-preview` confirms that regeneration leaves no drift. The merged commit still receives the explicit final `main` CI and CodeQL runs.
|
||||
- The test runner emits timing telemetry for measurement. Deterministic sharding is an explicit local opt-in through `npm run test:local -- --shard-index N --shard-count M`; required CI continues to run the complete unsharded `npm run test` gate.
|
||||
|
||||
**How you merge:**
|
||||
|
||||
- **Always merge with `npm run merge:batch`**, which uses GitHub's immediate squash-merge endpoint so the PR shows as **Merged** and the contributor gets credit. Do **not** integrate locally, use a raw merge command, or close the PR after copying its changes.
|
||||
@@ -192,7 +193,9 @@ Use this playbook:
|
||||
2. **Treat the checklist as guidance, not evidence.** A missing checklist emits a notice; objective path, blob, validation, reference, provenance, security, test, and exact-head review gates determine mergeability.
|
||||
3. **Let `merge:batch` approve action-required fork runs.** GitHub Actions materializes those runs asynchronously, so an empty first lookup is not evidence that approval is unnecessary. Do not approve them directly by run ID; the command binds every approval to the current PR, exact head SHA, allowlisted workflow, locally recomputed diff, and immutable PR tuple.
|
||||
4. **Wait for the required checks.** Merge only after `pr-policy`, `pr-evidence`, `source-validation`, `artifact-preview`, and a truthful skill-review outcome for any change under `skills/**` or `plugins/**/skills/**`. `review` means Tessl semantic review actually passed or reused a successful result for the identical complete skill-directory fingerprint. `manual-review-required` means credentials or credits were unavailable, or Tessl did not produce a passing result; it requires the exact-SHA maintainer judgment above. Never describe `manual-review-required` as “Tessl passed,” and never rerun Tessl merely because the PR head or base moved when the complete changed skill content is identical.
|
||||
5. **If the merge endpoint says `Base branch was modified`**, refresh the PR state and retry. This is normal when you are merging a batch and `main` moved between attempts.
|
||||
5. **If the merge endpoint says `Base branch was modified`**, stop that invocation, discard its stale evidence, refresh the checkout to the current `origin/main`, and rerun `merge:batch`. The command does not retry base drift automatically.
|
||||
|
||||
`merge:batch` evaluates the PR as it exists. It does not rewrite or normalize the PR body, and it does not close or reopen the PR to manufacture replacement workflow runs. The reopen procedure below is only for repairing a PR that was historically closed after unsupported local integration.
|
||||
|
||||
**If a PR was closed after local integration (reopen and merge):**
|
||||
|
||||
@@ -233,47 +236,47 @@ We used this flow for PRs [#220](https://github.com/sickn33/agentic-awesome-skil
|
||||
```text
|
||||
Fixed in #<PR_NUMBER>. Shipped in release vX.Y.Z.
|
||||
```
|
||||
3. **Run the Post-Merge Credits Sync below** — this is mandatory after every PR merge, including single-PR merges.
|
||||
3. **Complete the post-batch credits verification below** after the source batch, including a one-PR batch.
|
||||
|
||||
**Maintainer shortcut for batched PRs:**
|
||||
|
||||
- Use `npm run merge:batch -- --prs 450,449,446,451` to automate the ordered maintainer flow for multiple PRs. See [docs/maintainers/merge-batch.md](../docs/maintainers/merge-batch.md) for the short usage guide.
|
||||
- Pages is release-only: ordinary pushes to `main` never deploy it. Dispatch `.github/workflows/pages.yml` explicitly only at an approved publication gate. Canonical-sync merges still use `--skip-pages` and carry `[skip pages]` as a durable audit marker; the four routine app-bound checks and CodeQL remain enforced. The supported Core preview uses the targeted packed smoke workflow; retired certified-v1 verifier harnesses are not part of the repository workflow.
|
||||
- The script keeps the GitHub-only squash merge rule, handles fork-run approvals and stale PR metadata refresh, waits only on fresh required checks, retries `Base branch was modified`, and runs the mandatory post-merge `sync:contributors` follow-up on `main`. Sensitive repository-wide source changes use the same-repository exception only when the PR is authored by the repository owner and its exact full head SHA is attested; collaborator-authored sensitive PRs remain under the external safety policy.
|
||||
- Pages is release-only: ordinary pushes to `main` never deploy it. Dispatch `.github/workflows/pages.yml` only from the exact immutable `vX.Y.Z` tag at an approved publication gate, never from `main` or another branch. Canonical-sync merges still use `--skip-pages` and carry `[skip pages]` as a durable audit marker; the four routine app-bound checks and CodeQL remain enforced. The supported Core preview uses the targeted packed smoke workflow; retired certified-v1 verifier harnesses are not part of the repository workflow.
|
||||
- The script keeps the GitHub-only squash merge rule, handles guarded fork-run approvals, waits on required checks bound to the current PR and exact head, and hands contributor/generated drift to the protected canonical-sync lane. It does not run `sync:contributors` itself, mutate PR metadata, close/reopen PRs, or retry base drift; rerun it from fresh `origin/main` whenever the base or head moves. Sensitive repository-wide source changes use the same-repository exception only when the PR is authored by the repository owner and its exact full head SHA is attested; collaborator-authored sensitive PRs remain under the external safety policy.
|
||||
- It is intentionally not a conflict resolver. If a PR is conflicting, stop and follow the manual conflict playbook.
|
||||
|
||||
### C. Post-Merge Credits Sync (Mandatory After Every PR Merge)
|
||||
### C. Post-Batch Credits Verification
|
||||
|
||||
This section is **not optional**. Every time a PR is merged, you must ensure both README credit surfaces are correct on `main`:
|
||||
After every source batch, including a one-PR batch, verify that both README credit surfaces converge correctly on protected `main`:
|
||||
|
||||
- `### Community Contributors` / `## Credits & Sources` for external repositories referenced by the merged work
|
||||
- `## Repo Contributors` for the human contributor list
|
||||
|
||||
Do this **immediately after each PR merge**. Do not defer it to release prep.
|
||||
Do not run a local generator after every individual merge. The trusted `main` workflow coalesces contributor and generated drift in the protected canonical-sync PR after the source batch.
|
||||
|
||||
1. **Pull the merged `main` state locally**:
|
||||
1. **Pull the final source-batch state locally**:
|
||||
```bash
|
||||
git checkout main
|
||||
git pull --ff-only origin main
|
||||
```
|
||||
|
||||
2. **Sync `Repo Contributors`**:
|
||||
- Run: `npm run sync:contributors`
|
||||
- This refreshes `## Repo Contributors` in `README.md` from the live GitHub contributor list while preserving custom bot/app links.
|
||||
- If you are already doing a full maintainer sweep, `npm run sync:repo-state` is also acceptable.
|
||||
2. **Verify the canonical-sync handoff**:
|
||||
- Let the trusted workflow run `sync:repo-state`, which includes `sync:contributors`, and open or update `automation/canonical-repo-state` when drift exists.
|
||||
- Verify that the protected canonical PR contains the expected `## Repo Contributors` update while preserving custom bot/app links.
|
||||
- Do not commit generated or contributor drift to an ordinary source PR and do not push it directly to `main`.
|
||||
|
||||
3. **Audit external-source credits for the merged PR**:
|
||||
- Read the merged PR description, changed files, linked issues, and any release-note draft text you plan to ship.
|
||||
- If the PR added skills, references, or content sourced from an external GitHub repo that is not already credited in `README.md`, add it immediately.
|
||||
3. **Audit external-source credits for the source batch**:
|
||||
- Read the merged PR descriptions, changed files, linked issues, and any release-note draft text you plan to ship.
|
||||
- External-source credits should already have passed the source-PR credit gate. If the batch still reveals a missing or inaccurate README credit, treat that as unmanaged source repair rather than generated canonical drift.
|
||||
- Treat skill frontmatter `source_repo` + `source_type` as the primary source of truth when present.
|
||||
- If the repo is from an official organization/project source, place it under `### Official Sources`.
|
||||
- If the repo is a non-official ecosystem/community source, place it under `### Community Contributors`.
|
||||
- If the PR reveals that a credited repo is dead, renamed, archived, or overstated, fix the README entry in the same follow-up pass instead of leaving stale metadata behind.
|
||||
- Release notes are not a substitute for README attribution. If a repo appears in the merged work or planned release notes and belongs in credits, add it to the README at merge time.
|
||||
|
||||
4. **Publish README credit updates through the protected sync lane**:
|
||||
- After the source batch, let the trusted canonical-sync workflow open or update `automation/canonical-repo-state` and merge that PR after its required checks.
|
||||
- If an unmanaged credit repair is still required, make it on a topic branch and merge it by pull request; never push the follow-up directly to `main`.
|
||||
4. **Complete convergence through the correct protected lane**:
|
||||
- Merge the managed-only canonical-sync PR after its required checks.
|
||||
- If an unmanaged external-source credit repair is still required, make it on a topic branch and merge it by pull request; never add it to the canonical-sync PR or push it directly to `main`.
|
||||
- Do not leave contributor or community-credit drift until the next release.
|
||||
|
||||
5. **Then continue with normal maintenance**:
|
||||
|
||||
@@ -18,6 +18,10 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('run-{0}', github.run_id) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
candidate:
|
||||
name: preview candidate
|
||||
|
||||
@@ -14,6 +14,10 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('run-{0}', github.run_id) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
actionlint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
+113
-27
@@ -19,6 +19,10 @@ permissions:
|
||||
env:
|
||||
IS_TRUSTED_CANONICAL_SYNC_PR: ${{ inputs.canonical_sync_pr == true || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.head_ref == 'automation/canonical-repo-state' && github.event.pull_request.user.login == 'github-actions[bot]') }}
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('run-{0}', github.run_id) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
pr-policy:
|
||||
if: github.event_name == 'pull_request' || inputs.canonical_sync_pr == true
|
||||
@@ -30,6 +34,9 @@ jobs:
|
||||
direct_derived_changes_count: ${{ steps.intake.outputs.direct_derived_changes_count }}
|
||||
has_quality_checklist: ${{ steps.intake.outputs.has_quality_checklist }}
|
||||
has_issue_link: ${{ steps.intake.outputs.has_issue_link }}
|
||||
fork_approval_safe: ${{ steps.intake.outputs.fork_approval_safe }}
|
||||
impact_profile: ${{ steps.intake.outputs.impact_profile }}
|
||||
impact_reasons: ${{ steps.intake.outputs.impact_reasons }}
|
||||
steps:
|
||||
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
|
||||
with:
|
||||
@@ -52,10 +59,14 @@ jobs:
|
||||
id: intake
|
||||
if: github.event_name == 'pull_request' && env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: |
|
||||
node tools/scripts/pr_preflight.cjs \
|
||||
--base "origin/${{ github.base_ref }}" \
|
||||
--head "HEAD" \
|
||||
trusted_root="$RUNNER_TEMP/pr-policy-main"
|
||||
git worktree add --detach "$trusted_root" "${{ github.event.pull_request.base.sha }}"
|
||||
NODE_PATH="$GITHUB_WORKSPACE/node_modules" node "$trusted_root/tools/scripts/pr_preflight.cjs" \
|
||||
--repo "$GITHUB_WORKSPACE" \
|
||||
--base "${{ github.event.pull_request.base.sha }}" \
|
||||
--head "${{ github.event.pull_request.head.sha }}" \
|
||||
--event-path "$GITHUB_EVENT_PATH" \
|
||||
--check-fork-safety \
|
||||
--no-run \
|
||||
--write-github-output \
|
||||
--write-step-summary
|
||||
@@ -107,10 +118,6 @@ jobs:
|
||||
actual_tree=$(git -C "$GITHUB_WORKSPACE" rev-parse 'HEAD^{tree}')
|
||||
test "$expected_tree" = "$actual_tree"
|
||||
|
||||
- name: Install npm dependencies
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR == 'true'
|
||||
run: npm ci --ignore-scripts
|
||||
|
||||
- name: Enforce PR source-only contract
|
||||
if: github.event_name == 'pull_request' && env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
env:
|
||||
@@ -137,32 +144,43 @@ jobs:
|
||||
source-validation:
|
||||
if: github.event_name == 'pull_request' || inputs.canonical_sync_pr == true
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pr-policy, pr-evidence]
|
||||
needs: pr-policy
|
||||
outputs:
|
||||
preview_manifest_digest: ${{ steps.preview_manifest.outputs.manifest_digest }}
|
||||
steps:
|
||||
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install Python dependencies
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: pip install -r tools/requirements.txt
|
||||
|
||||
- name: Set up Node
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
|
||||
- name: Fetch base branch
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: git fetch origin "${{ github.base_ref || 'main' }}"
|
||||
|
||||
- name: Install npm dependencies
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: npm ci
|
||||
|
||||
- name: Verify directory structure
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: |
|
||||
test -d skills/
|
||||
test -d apps/web-app/
|
||||
@@ -172,9 +190,11 @@ jobs:
|
||||
test -f CONTRIBUTING.md
|
||||
|
||||
- name: Validate source changes
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: npm run validate
|
||||
|
||||
- name: Enforce validation warning budget
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: npm run check:warning-budget
|
||||
|
||||
- name: Verify README source credits for changed skills
|
||||
@@ -182,44 +202,98 @@ jobs:
|
||||
run: npm run check:readme-credits -- --base "origin/${{ github.base_ref }}" --head HEAD
|
||||
|
||||
- name: Validate references
|
||||
if: needs.pr-policy.outputs.requires_references == 'true'
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true' && needs.pr-policy.outputs.requires_references == 'true'
|
||||
run: npm run validate:references
|
||||
|
||||
- name: Refresh ephemeral derived sources for tests
|
||||
run: npm run plugin-compat:sync && npm run index && npm run bundles:sync && npm run sync:metadata && npm run catalog && npm run build:aas-v1-catalog
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: npm run plugin-compat:sync && npm run index && npm run bundles:sync && npm run sync:metadata && npm run catalog && npm run build:aas-v1-catalog && npm run sync:web-assets
|
||||
|
||||
- name: Run tests
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: npm run test
|
||||
|
||||
- name: Run docs security checks
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: npm run security:docs
|
||||
|
||||
- name: Create exact-head artifact preview manifest
|
||||
id: preview_manifest
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
env:
|
||||
CATEGORIES_CSV: ${{ needs.pr-policy.outputs.categories }}
|
||||
PRIMARY_CATEGORY: ${{ needs.pr-policy.outputs.primary_category }}
|
||||
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mapfile -t managed_files < <(node tools/scripts/generated_files.js --include-mixed)
|
||||
if [ "${#managed_files[@]}" -eq 0 ]; then
|
||||
echo "::error::No managed files resolved from generated_files contract."
|
||||
exit 1
|
||||
fi
|
||||
mapfile -d '' -t drift_files < <(git diff --name-only -z -- "${managed_files[@]}")
|
||||
categories_json=$(node -e 'process.stdout.write(JSON.stringify(process.argv[1].split(",").filter(Boolean).sort()))' "$CATEGORIES_CSV")
|
||||
args=()
|
||||
for drift_file in "${drift_files[@]}"; do
|
||||
args+=(--drift-file "$drift_file")
|
||||
done
|
||||
node tools/scripts/ci_artifact_preview.cjs create \
|
||||
--output .tmp/artifact-preview/manifest.json \
|
||||
--mode source-preview \
|
||||
--repository "$GITHUB_REPOSITORY" \
|
||||
--run-id "$GITHUB_RUN_ID" \
|
||||
--run-attempt "$GITHUB_RUN_ATTEMPT" \
|
||||
--workflow-sha "$GITHUB_WORKFLOW_SHA" \
|
||||
--head-sha "$PR_HEAD_SHA" \
|
||||
--primary-category "$PRIMARY_CATEGORY" \
|
||||
--categories-json "$categories_json" \
|
||||
"${args[@]}" \
|
||||
--write-github-output
|
||||
|
||||
- name: Upload exact-head artifact preview manifest
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: source-preview-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
path: .tmp/artifact-preview/manifest.json
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
|
||||
- name: Record canonical source-validation boundary
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR == 'true'
|
||||
run: echo "Canonical source state and exact generated tree were reproduced by required pr-policy."
|
||||
|
||||
pr-evidence:
|
||||
if: github.event_name == 'pull_request' || inputs.canonical_sync_pr == true
|
||||
runs-on: ubuntu-latest
|
||||
needs: pr-policy
|
||||
steps:
|
||||
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Set up Node
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
|
||||
- name: Install trusted dependencies
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: |
|
||||
pip install -r tools/requirements.txt
|
||||
npm ci --ignore-scripts
|
||||
|
||||
- name: Fetch base branch
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
run: git fetch origin "${{ github.base_ref || 'main' }}"
|
||||
|
||||
- name: Generate PR intake JSON
|
||||
@@ -294,31 +368,52 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR == 'true'
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install Python dependencies
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR == 'true'
|
||||
run: pip install -r tools/requirements.txt
|
||||
|
||||
- name: Set up Node
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR == 'true'
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
|
||||
- name: Install npm dependencies
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR == 'true'
|
||||
run: npm ci
|
||||
|
||||
- name: Generate canonical artifacts preview
|
||||
- name: Download exact-head artifact preview manifest
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: source-preview-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
path: .tmp/artifact-preview
|
||||
|
||||
- name: Verify and report exact-head artifact preview
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR != 'true'
|
||||
env:
|
||||
EXPECTED_DIGEST: ${{ needs.source-validation.outputs.preview_manifest_digest }}
|
||||
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
npm run chain
|
||||
npm run catalog
|
||||
npm run sync:web-assets
|
||||
node "$GITHUB_WORKSPACE/tools/scripts/ci_artifact_preview.cjs" verify-summary \
|
||||
--manifest .tmp/artifact-preview/manifest.json \
|
||||
--expected-repository "$GITHUB_REPOSITORY" \
|
||||
--expected-run-id "$GITHUB_RUN_ID" \
|
||||
--expected-run-attempt "$GITHUB_RUN_ATTEMPT" \
|
||||
--expected-workflow-sha "$GITHUB_WORKFLOW_SHA" \
|
||||
--expected-head-sha "$PR_HEAD_SHA" \
|
||||
--expected-digest "$EXPECTED_DIGEST" \
|
||||
--write-step-summary
|
||||
|
||||
- name: Reproduce canonical-sync PR from main
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR == 'true'
|
||||
@@ -327,6 +422,7 @@ jobs:
|
||||
run: npm run sync:repo-state
|
||||
|
||||
- name: Report generated drift
|
||||
if: env.IS_TRUSTED_CANONICAL_SYNC_PR == 'true'
|
||||
run: |
|
||||
mapfile -t managed_files < <(node tools/scripts/generated_files.js --include-mixed)
|
||||
if [ "${#managed_files[@]}" -eq 0 ]; then
|
||||
@@ -350,19 +446,9 @@ jobs:
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$IS_TRUSTED_CANONICAL_SYNC_PR" = "true" ]; then
|
||||
echo "::error::Canonical-sync PR is not byte-for-byte reproducible from main."
|
||||
printf '%s\n' "$drift_files"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "::notice::Generated drift detected in artifact preview."
|
||||
{
|
||||
echo "- Generated drift: detected"
|
||||
echo
|
||||
echo "Predicted file updates:"
|
||||
printf '%s\n' "$drift_files" | sed "s/^/- \`/; s/\$/\`/"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "::error::Canonical-sync PR is not byte-for-byte reproducible from main."
|
||||
printf '%s\n' "$drift_files"
|
||||
exit 1
|
||||
|
||||
main-validation-and-sync:
|
||||
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.canonical_sync_pr != true && github.ref == 'refs/heads/main')
|
||||
|
||||
@@ -14,6 +14,10 @@ permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('run-{0}', github.run_id) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
|
||||
@@ -7,6 +7,10 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('run-{0}', github.run_id) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
dependency-review:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -29,6 +29,44 @@ jobs:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Verify release provenance
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "${GITHUB_REF_TYPE}" != "tag" ]]; then
|
||||
echo "Pages deployment must be dispatched from an immutable release tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${GITHUB_REF_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Pages deployment tag must match vX.Y.Z exactly: ${GITHUB_REF_NAME}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
package_version="$(jq -r '.version // empty' package.json)"
|
||||
expected_tag="v${package_version}"
|
||||
if [[ "${GITHUB_REF_NAME}" != "${expected_tag}" ]]; then
|
||||
echo "Pages deployment tag ${GITHUB_REF_NAME} does not match package.json ${expected_tag}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tag_commit="$(git rev-parse "refs/tags/${GITHUB_REF_NAME}^{commit}")"
|
||||
head_commit="$(git rev-parse HEAD)"
|
||||
if [[ "${tag_commit}" != "${GITHUB_SHA}" || "${head_commit}" != "${GITHUB_SHA}" ]]; then
|
||||
echo "Pages deployment tag, checkout, and workflow SHA must resolve to the same commit." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
release_json="$(gh api --method GET "repos/${GITHUB_REPOSITORY}/releases/tags/${GITHUB_REF_NAME}")"
|
||||
if ! jq -e --arg tag "${GITHUB_REF_NAME}" \
|
||||
'.tag_name == $tag and .draft == false and (.published_at | type == "string" and length > 0)' \
|
||||
<<<"${release_json}" >/dev/null; then
|
||||
echo "Pages deployment requires a published, non-draft GitHub Release for ${GITHUB_REF_NAME}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
|
||||
with:
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
# Build and deploy the web app to GitHub Pages.
|
||||
# Enable in repo: Settings → Pages → Source: GitHub Actions.
|
||||
# Site URL: https://<owner>.github.io/<repo>/
|
||||
|
||||
name: Deploy Web App to GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main", "master"]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install root dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Prepare web app (index + skills)
|
||||
run: npm run app:setup
|
||||
|
||||
- name: Install web-app dependencies
|
||||
run: cd apps/web-app && npm ci
|
||||
|
||||
- name: Build web app for GitHub Pages
|
||||
run: cd apps/web-app && npm run build
|
||||
env:
|
||||
VITE_BASE_PATH: /${{ github.event.repository.name }}/
|
||||
SEO_SITE_URL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}
|
||||
|
||||
- name: Validate SEO artifact quality
|
||||
run: cd apps/web-app && npm run verify:seo
|
||||
|
||||
- name: Validate generated sitemap and asset consistency
|
||||
run: |
|
||||
cd apps/web-app
|
||||
test -f dist/robots.txt
|
||||
test -f dist/sitemap.xml
|
||||
test -f dist/site.webmanifest
|
||||
|
||||
- name: Prepare artifact (404 + .nojekyll)
|
||||
run: |
|
||||
cd apps/web-app/dist
|
||||
cp index.html 404.html
|
||||
touch .nojekyll
|
||||
test -f 404.html
|
||||
|
||||
- name: Configure GitHub Pages
|
||||
uses: actions/configure-pages@v5
|
||||
|
||||
- name: Upload Pages artifact
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
with:
|
||||
path: apps/web-app/dist
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deploy.outputs.page_url }}
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deploy
|
||||
uses: actions/deploy-pages@v4
|
||||
@@ -8,6 +8,10 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('run-{0}', github.run_id) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
review-state:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
Reference in New Issue
Block a user