Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: CI
on:
push:
branches: [master]
pull_request:
types: [opened, synchronize, reopened]
merge_group:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
tests:
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: '3.13'
- name: Install YAML validator
run: |
python3 -m venv .build/venv
.build/venv/bin/python -m pip install --disable-pip-version-check --no-cache-dir -r requirements-test.txt
- name: Test scripts and workflow contracts
run: |
.build/venv/bin/python -m unittest discover -s tests
.build/venv/bin/python scripts/check-workflows.py
.build/venv/bin/python scripts/plugin-runtime.py check-workflow
git diff --exit-code
validate:
if: always()
needs: tests
uses: ./.github/workflows/result.yml
with:
needs-json: ${{ toJSON(needs) }}
73 changes: 73 additions & 0 deletions .github/workflows/organization.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Organization
on:
workflow_call:
inputs:
declaration-revision:
description: Full .github SHA owning both MAINTENANCE.md and profile/catalog.json
type: string
required: true
mode:
description: online reads GitHub; offline checks the bundled fixture
type: string
default: online
scope:
description: membership checks inventory and About; full adds declared settings
type: string
default: full
secrets:
organization-token:
description: Read access to organization/member settings, Apps and credential names
required: false
outputs:
declaration-revision:
description: Checked declaration revision (fixture label in offline mode)
value: ${{ jobs.organization.outputs.declaration-revision }}
permissions: {}
jobs:
organization:
runs-on: ubuntu-24.04
timeout-minutes: 20
permissions:
contents: read
outputs:
declaration-revision: ${{ inputs.declaration-revision }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .shared
persist-credentials: false
- name: Validate inputs
env:
REVISION: ${{ inputs.declaration-revision }}
MODE: ${{ inputs.mode }}
SCOPE: ${{ inputs.scope }}
shell: bash
run: |
[[ "$REVISION" =~ ^[0-9a-f]{40}$ ]]
[[ "$MODE" == online || "$MODE" == offline ]]
[[ "$SCOPE" == membership || "$SCOPE" == full ]]
- if: inputs.mode == 'online'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: computer-mcp/.github
ref: ${{ inputs.declaration-revision }}
path: declaration
persist-credentials: false
- name: Check organization
env:
GH_TOKEN: ${{ secrets.organization-token || github.token }}
DECLARATION_REVISION: ${{ inputs.declaration-revision }}
MODE: ${{ inputs.mode }}
SCOPE: ${{ inputs.scope }}
shell: bash
run: |
if [[ "$MODE" == offline ]]; then
python3 -I .shared/scripts/check-organization.py --mode offline \
--declaration-root .shared/fixtures/declaration --declaration-revision "$DECLARATION_REVISION" \
--fixture .shared/fixtures/organization.json --scope "$SCOPE"
else
python3 -I .shared/scripts/check-organization.py --mode online \
--declaration-root declaration --declaration-revision "$DECLARATION_REVISION" --scope "$SCOPE"
fi
170 changes: 170 additions & 0 deletions .github/workflows/plugin-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
name: Plugin release
on:
workflow_call:
inputs:
ref:
description: Signed annotated version tag, or a commit for a dry run
type: string
required: true
publish:
description: Publish the verified release (false assembles a dry-run bundle)
type: boolean
default: false
build:
description: Build command; the workflow appends the output directory as its final argument
type: string
required: true
ci_artifact:
description: Exact ci.yml artifact name; ${commit} expands to the resolved commit
type: string
required: true
runner:
description: Runner for the isolated caller build
type: string
default: ubuntu-24.04
outputs:
published:
description: True only when a complete immutable release is public
value: ${{ jobs.publish.outputs.published || 'false' }}
release_id:
description: Published GitHub Release ID (empty for a dry run)
value: ${{ jobs.publish.outputs.release_id }}
tag:
description: Verified version tag (empty for an untagged dry run)
value: ${{ jobs.verify.outputs.tag }}
permissions: {}
env:
PLUGIN_RELEASE_SHA256: 'a7622635843b200caf28dc61edc905eb1ec53c696b54794dbadf786063d130d9'
jobs:
source:
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: read
actions: read
outputs:
commit: ${{ steps.source.outputs.commit }}
workflow_ref: ${{ steps.source.outputs.workflow_ref }}
workflow_sha: ${{ steps.source.outputs.workflow_sha }}
steps:
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: '3.13'
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .shared
persist-credentials: false
- name: Resolve and verify the source ref
id: source
env:
GH_TOKEN: ${{ github.token }}
GH_REPOSITORY: ${{ github.repository }}
RELEASE_REF: ${{ inputs.ref }}
RELEASE_PUBLISH: ${{ inputs.publish }}
RELEASE_WORKFLOW_REF: ${{ job.workflow_ref }}
RELEASE_WORKFLOW_SHA: ${{ job.workflow_sha }}
shell: bash
run: python3 -I .shared/scripts/release-step.py source
build:
needs: source
runs-on: ${{ inputs.runner }}
timeout-minutes: 30
permissions: {}
outputs:
artifact_id: ${{ steps.upload.outputs.artifact-id }}
steps:
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: '3.13'
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.source.outputs.commit }}
persist-credentials: false
- name: Build the caller's archives
env:
RELEASE_BUILD: ${{ inputs.build }}
shell: bash
run: |
bash -euo pipefail -c "$RELEASE_BUILD \"\$1\"" plugin-build "$RUNNER_TEMP/plugin-release-build"
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
id: upload
with:
name: plugin-build-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/plugin-release-build/
if-no-files-found: error
retention-days: 14
verify:
needs: [source, build]
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: read
actions: read
outputs:
tag: ${{ steps.bundle.outputs.tag }}
asset_digests: ${{ steps.bundle.outputs.asset_digests }}
artifact_id: ${{ steps.upload.outputs.artifact-id }}
steps:
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: '3.13'
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .shared
persist-credentials: false
- name: Verify the helper, compare archive bytes and assemble the bundle
id: bundle
env:
GH_TOKEN: ${{ github.token }}
GH_REPOSITORY: ${{ github.repository }}
RELEASE_REF: ${{ inputs.ref }}
RELEASE_PUBLISH: ${{ inputs.publish }}
RELEASE_BUILD_ARTIFACT_ID: ${{ needs.build.outputs.artifact_id }}
RELEASE_COMMIT: ${{ needs.source.outputs.commit }}
GH_RUN_ID: ${{ github.run_id }}
RELEASE_CI_ARTIFACT: ${{ inputs.ci_artifact }}
RELEASE_WORKFLOW_REF: ${{ needs.source.outputs.workflow_ref }}
RELEASE_WORKFLOW_SHA: ${{ needs.source.outputs.workflow_sha }}
shell: bash
run: python3 -I .shared/scripts/release-step.py verify
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
id: upload
with:
name: plugin-release-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/plugin-release/
if-no-files-found: error
retention-days: 14
publish:
if: inputs.publish
needs: verify
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: write
outputs:
published: ${{ steps.release.outputs.published }}
release_id: ${{ steps.release.outputs.release_id }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .shared
persist-credentials: false
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
artifact-ids: ${{ needs.verify.outputs.artifact_id }}
path: ${{ runner.temp }}/plugin-release
merge-multiple: true
- name: Verify the helper and publish only the verified bundle
id: release
env:
GH_TOKEN: ${{ github.token }}
GH_REPOSITORY: ${{ github.repository }}
RELEASE_ASSET_DIGESTS: ${{ needs.verify.outputs.asset_digests }}
shell: bash
run: python3 -I .shared/scripts/release-step.py publish
26 changes: 26 additions & 0 deletions .github/workflows/plugin-runtime.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Plugin runtime
on:
workflow_call:
permissions:
contents: read
jobs:
runtime:
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .shared
persist-credentials: false
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: member
persist-credentials: false
- name: Verify shared Python runtime
env:
PLUGIN_RUNTIME_SHA256: '5a9f797bfca4b6ab31a9a648017fb1d09400593a9aab0d2250d426efa51f97cf'
run: |
python3 -I .shared/scripts/plugin-runtime.py check-workflow
python3 -I .shared/scripts/plugin-runtime.py check member
58 changes: 58 additions & 0 deletions .github/workflows/policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Source policy
on:
workflow_call:
inputs:
declaration-revision:
description: Full commit SHA of computer-mcp/.github containing MAINTENANCE.md
type: string
required: true
path-exceptions:
description: Newline-separated repository-relative globs for documented path exceptions
type: string
default: ''
outputs:
declaration-revision:
description: Enforced MAINTENANCE revision
value: ${{ jobs.policy.outputs.declaration-revision }}
permissions: {}
jobs:
policy:
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: read
outputs:
declaration-revision: ${{ inputs.declaration-revision }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .shared
persist-credentials: false
- name: Validate declaration revision
env:
REVISION: ${{ inputs.declaration-revision }}
run: '[[ "$REVISION" =~ ^[0-9a-f]{40}$ ]]'
shell: bash
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: computer-mcp/.github
ref: ${{ inputs.declaration-revision }}
path: declaration
persist-credentials: false
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
path: member
fetch-depth: 0
persist-credentials: false
- name: Check source policy
env:
GH_TOKEN: ${{ github.token }}
PATH_EXCEPTIONS: ${{ inputs.path-exceptions }}
DECLARATION_REVISION: ${{ inputs.declaration-revision }}
run: >-
python3 -I .shared/scripts/check-policy.py --root member
--declaration-root declaration --declaration-revision "$DECLARATION_REVISION"
--path-exceptions "$PATH_EXCEPTIONS"
Loading