-
Notifications
You must be signed in to change notification settings - Fork 0
ci: configure Context7 and trusted maintenance automation #255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,9 +14,6 @@ concurrency: | |
| group: ci-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| env: | ||
| NODE_VERSION: '22' | ||
|
|
||
|
|
@@ -43,6 +40,33 @@ env: | |
| # pointing at a local models/ dir. | ||
|
|
||
| jobs: | ||
| policy: | ||
| name: CI policy | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| outputs: | ||
| run_ci: ${{ steps.classify.outputs.run_ci }} | ||
| steps: | ||
| - id: classify | ||
| name: Classify trusted maintenance pull requests | ||
| env: | ||
| EVENT_NAME: ${{ github.event_name }} | ||
| PR_AUTHOR: ${{ github.event.pull_request.user.login }} | ||
| PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} | ||
| PR_HEAD_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }} | ||
| REPOSITORY: ${{ github.repository }} | ||
| run: | | ||
| run_ci=true | ||
| if [ "$EVENT_NAME" = "pull_request" ] && [ "$PR_HEAD_REPOSITORY" = "$REPOSITORY" ]; then | ||
| if [[ "$PR_HEAD_REF" == release-please--* ]]; then | ||
| run_ci=false | ||
|
Comment on lines
+63
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a collaborator opens an internal PR from a branch named Useful? React with 👍 / 👎. |
||
| elif [ "$PR_AUTHOR" = "dependabot[bot]" ] && [[ "$PR_HEAD_REF" == *-non-major-* ]]; then | ||
| run_ci=false | ||
|
Comment on lines
+65
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a user with write access pushes to an existing grouped Dependabot branch, the PR author remains Useful? React with 👍 / 👎. |
||
| fi | ||
| fi | ||
| echo "run_ci=$run_ci" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # Every job installs with `pnpm install --frozen-lockfile` against pnpm's | ||
| # native content-addressed store cache (setup-node cache:'pnpm'). The | ||
| # frozen lockfile guarantees identical resolved bytes across jobs, and the | ||
|
|
@@ -52,6 +76,8 @@ jobs: | |
| # "leverage each action's own caching" approach; no custom pack/restore. | ||
| check: | ||
| name: ${{ matrix.task }} | ||
| needs: [policy] | ||
| if: needs.policy.outputs.run_ci == 'true' | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| fail-fast: false | ||
|
|
@@ -87,7 +113,8 @@ jobs: | |
| # Sourcey is the sole production renderer. This safe pull_request job builds | ||
| # from the checked-out change but never deploys or receives credentials. | ||
| name: Sourcey Docs Build | ||
| needs: [check] | ||
| needs: [policy, check] | ||
| if: always() && needs.policy.outputs.run_ci == 'true' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
|
|
@@ -123,7 +150,8 @@ jobs: | |
| # actually composes into a working game (per RFC 0001 §D-test-topology). A green | ||
| # library but red examples means the public surface or a binding regressed. | ||
| name: Examples (consumer e2e) | ||
| needs: [check] | ||
| needs: [policy, check] | ||
| if: always() && needs.policy.outputs.run_ci == 'true' | ||
|
Comment on lines
+154
to
+155
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
On an ordinary contributor PR where any Useful? React with 👍 / 👎. |
||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
|
|
@@ -171,6 +199,8 @@ jobs: | |
|
|
||
| coverage: | ||
| name: Coverage | ||
| needs: [policy] | ||
| if: needs.policy.outputs.run_ci == 'true' | ||
| runs-on: ubuntu-latest | ||
| # Library scripts (test:coverage, coverage:merge:enforce), src/cli, and the | ||
| # coverage/ output are all package-level — run this job's steps from the | ||
|
|
@@ -241,7 +271,8 @@ jobs: | |
|
|
||
| dependency-review: | ||
| name: Dependency Review | ||
| if: github.event_name == 'pull_request' | ||
| needs: [policy] | ||
| if: needs.policy.outputs.run_ci == 'true' && github.event_name == 'pull_request' | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
|
|
@@ -259,7 +290,8 @@ jobs: | |
|
|
||
| semgrep: | ||
| name: Semgrep SAST | ||
| needs: check | ||
| needs: [policy, check] | ||
| if: always() && needs.policy.outputs.run_ci == 'true' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| { | ||
| "$schema": "https://context7.com/schema/context7.json", | ||
| "projectTitle": "Declarative Hex Worlds", | ||
| "description": "A Koota-first, declarative 2.5D hex-gameboard runtime with recipes, scenarios, simulation, rendering, and KayKit asset support.", | ||
| "branch": "main", | ||
| "folders": [ | ||
| "docs", | ||
| "packages/declarative-hex-worlds/docs", | ||
| "packages/declarative-hex-worlds/src", | ||
| "examples" | ||
| ], | ||
| "excludeFolders": [ | ||
| ".git", | ||
| "node_modules", | ||
| "dist", | ||
| "coverage", | ||
| "references", | ||
| "models", | ||
| "tests", | ||
| "docs/dist" | ||
| ], | ||
| "excludeFiles": [ | ||
| "CHANGELOG.md" | ||
| ], | ||
| "rules": [ | ||
| "Treat docs/ as the canonical user and agent documentation site; it is built with Sourcey.", | ||
| "Use the public runtime, recipe, scenario, simulation, and blueprint APIs instead of mutating Koota relation stores directly.", | ||
| "Keep FREE asset manifests publishable and fetch raw KayKit assets through bootstrap; never publish local references or EXTRA binaries.", | ||
| "Preserve footprint occupancy through the public placement and actor helpers, and validate serializable plans before runtime-specific checks." | ||
| ], | ||
| "previousVersions": [ | ||
| { | ||
| "tag": "declarative-hex-worlds@1.2.3" | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import { describe, expect, it } from 'vitest'; | ||
| import { findWorkspaceRoot } from '../setup/workspace-root'; | ||
| import { readFileSync } from 'node:fs'; | ||
| import { resolve } from 'node:path'; | ||
|
|
||
| interface Context7Config { | ||
| $schema?: string; | ||
| projectTitle?: string; | ||
| branch?: string; | ||
| folders?: string[]; | ||
| excludeFolders?: string[]; | ||
| rules?: string[]; | ||
| } | ||
|
|
||
| const workspaceRoot = findWorkspaceRoot(import.meta.dirname); | ||
| const config = JSON.parse( | ||
| readFileSync(resolve(workspaceRoot, 'context7.json'), 'utf8') | ||
| ) as Context7Config; | ||
|
|
||
| describe('Context7 owner configuration', () => { | ||
| it('pins the official schema and the canonical branch', () => { | ||
| expect(config.$schema).toBe('https://context7.com/schema/context7.json'); | ||
| expect(config.branch).toBe('main'); | ||
| expect(config.projectTitle).toBe('Declarative Hex Worlds'); | ||
| }); | ||
|
|
||
| it('indexes canonical documentation and public API source without local assets', () => { | ||
| expect(config.folders).toEqual( | ||
| expect.arrayContaining(['docs', 'packages/declarative-hex-worlds/docs', 'packages/declarative-hex-worlds/src']) | ||
| ); | ||
| expect(config.excludeFolders).toEqual( | ||
| expect.arrayContaining(['node_modules', 'references', 'models', 'tests', 'docs/dist']) | ||
| ); | ||
| expect(config.rules?.length).toBeGreaterThan(0); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: jbcom/declarative-hex-worlds
Length of output: 8565
🏁 Script executed:
Repository: jbcom/declarative-hex-worlds
Length of output: 25961
🌐 Web query:
GitHub Actions pull_request event github.actor release-please GitHub App branch pull request author behavior💡 Result:
When release-please or any automation creates a pull request via the GitHub API, the value of
github.actorin subsequent triggered workflows depends on the credentials used to perform that action [1][2]. If the action uses the defaultGITHUB_TOKEN, the pull request is created by the "GitHub Actions" bot, and the event often fails to triggerpull_requestworkflows at all [1][3]. This is a security feature designed to prevent recursive workflow execution [1][4][3]. If the action is configured to authenticate as a GitHub App (using a private key or a generated app token), the GitHub App is recognized as the creator of the pull request [1][5]. In this scenario: 1.github.actorwill be the name of the GitHub App (e.g.,release-please[bot]) [1][2]. 2. Because the GitHub App is treated as a separate actor, thepull_requestevent will fire normally, allowing your CI/CD pipelines to run on the release PR [1][5]. To ensure your workflows run on PRs created by release-please, it is best practice to authenticate with a GitHub App token [1][5]. Using a Personal Access Token (PAT) is an alternative, in which casegithub.actorwould be the owner of that PAT [6][4]. If you continue to use the defaultGITHUB_TOKEN, you may need to add apushtrigger for the specific branches created by release-please (e.g.,release-please--*) as a workaround to get your pipelines to execute [1][3].Citations:
🏁 Script executed:
Repository: jbcom/declarative-hex-worlds
Length of output: 50385
🌐 Web query:
release-please-action v5 token GitHub App pull request author branch release-please-- identity💡 Result:
In
release-please-actionv5, you can authenticate using a GitHub App installation token to create and manage pull requests [1][2]. Identity and Authentication When using a GitHub App, you typically exchange a private key and App ID for a short-lived installation token within your workflow using an action such asactions/create-github-app-token[1][2]. You provide this token to therelease-please-actionvia thetokeninput [2]: - uses: actions/create-github-app-token@v3 id: app-token with: client-id: ${{ secrets.APP_CLIENT_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} - uses: googleapis/release-please-action@v5 with: token: ${{ steps.app-token.outputs.token }} The action will then perform operations (such as creating or updating pull requests) as the GitHub App rather than the user who triggered the workflow [2]. Pull Request Authoring and Branching - Pull Request Branches:release-pleaseautomatically determines the head branch name for release pull requests (often prefixed withrelease-). If you are working with monorepos or multiple components, you may see branches or tags prefixed with a component name [3]. - Branch Conflict/Existing PRs: The action tracks existing release pull requests by looking for specific labels (such asautorelease: pending) [4]. If a pull request already exists for the current release candidate, it will attempt to update that existing pull request rather than opening a new one [1]. - Known Issues: There have been reports of edge cases where the action's internal logic for updating existing pull requests (via the legacycode-suggesterutility) may conflict with GitHub App tokens when determining if a pull request exists [1][5]. The project has been working on improvements to use the Git Data API directly for these operations to improve reliability [5]. - Identity: When the GitHub App performs these actions, the "author" of the pull request or commit will appear as the GitHub App (or the bot user associated with it) rather than the user who initiated the workflow [2][6]. Note that while a deprecated Probot-based "release-please" GitHub App existed, modern best practices involve using therelease-please-actionwith a minted GitHub App installation token [7][6].Citations:
🏁 Script executed:
Repository: jbcom/declarative-hex-worlds
Length of output: 416
🏁 Script executed:
Repository: jbcom/declarative-hex-worlds
Length of output: 6511
Do not trust the
release-please--branch prefix..github/workflows/automerge.yml: remove release-please branches from auto-merge. Release pull requests are documented as a human checkpoint..github/workflows/ci.yml: require the configured Release Please identity before settingrun_ci=false.workflows-contract.test.ts: assert both the identity check and the rejection of prefix-only trust.🧰 Tools
🪛 zizmor (1.29.0)
[error] 18-18: spoofable bot actor check (bot-conditions): actor context may be spoofable
(bot-conditions)
📍 Affects 3 files
.github/workflows/automerge.yml#L14-L22(this comment).github/workflows/ci.yml#L62-L66packages/declarative-hex-worlds/tests/contract/workflows-contract.test.ts#L296-L306🤖 Prompt for AI Agents