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
90 changes: 90 additions & 0 deletions .github/workflows/comment-trigger.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Comment Trigger

on:
issue_comment:
types: [created]

permissions:
contents: read
pull-requests: write
actions: write

jobs:
trigger-checks:
name: Trigger Checks from Comment
if: |
github.event.issue.pull_request &&
(github.event.comment.body == '/test all' ||
github.event.comment.body == '/test-all' ||
github.event.comment.body == '/run-all-checks') &&
(github.event.comment.author_association == 'OWNER' ||
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR')
runs-on: ubuntu-latest
steps:
- name: Get PR branch
uses: actions/github-script@v7
id: get-pr
with:
script: |
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});
return pr.data.head.ref;

- name: Add reaction to comment
uses: actions/github-script@v7
with:
script: |
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: 'rocket'
});

- name: Trigger Python CI
uses: actions/github-script@v7
with:
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'python.yml',
ref: '${{ fromJSON(steps.get-pr.outputs.result) }}'
});

- name: Trigger Go CI
uses: actions/github-script@v7
with:
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'go.yml',
ref: '${{ fromJSON(steps.get-pr.outputs.result) }}'
});

- name: Trigger TypeScript CI
uses: actions/github-script@v7
with:
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'typescript.yml',
ref: '${{ fromJSON(steps.get-pr.outputs.result) }}'
});

- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: 'πŸš€ All CI checks triggered! Check the Actions tab for progress.'
});
80 changes: 80 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Go CI
on:
push:
branches: [main]
paths:
- 'go/**'
- '.github/workflows/go.yml'
pull_request:
paths:
- 'go/**'
- '.github/workflows/go.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
go-lint:
name: "Linting"
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Go
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: "^1.25"
- name: Check formatting
run: |
cd go/sdk
unformatted=$(gofmt -l .)
if [ -n "$unformatted" ]; then
echo "The following files are not properly formatted:"
echo "$unformatted"
exit 1
fi
echo "All Go files are properly formatted"
- name: Run Go vet
run: |
cd go/sdk
go vet ./...
- name: Run staticcheck
uses: dominikh/staticcheck-action@288b4e28bae83c59f35f73651aeb5cab746a06fc # v1.4.0
with:
install-go: false
version: "v0.6.1"
working-directory: go/sdk

go-test:
name: "Unit Tests"
runs-on: ubuntu-latest
strategy:
matrix:
go: ["1.23", "1.24", "1.25"]
steps:
- name: Check out code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Go
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ matrix.go }}
- name: Test
run: |
cd go/sdk
go test -v ./...

go-race-test:
name: "Race Detection"
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Go
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: "1.24"
- name: Test with -race
run: |
cd go/sdk
go test -v -race ./...
67 changes: 67 additions & 0 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Python CI
on:
push:
branches: [main]
paths:
- 'python/**'
- '.github/workflows/python.yml'
pull_request:
paths:
- 'python/**'
- '.github/workflows/python.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
python-lint:
name: "Linting"
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
cd python/sdk
pip install -e .
pip install ruff mypy
- name: Run Ruff formatter check
run: |
cd python/sdk
ruff format --check .
- name: Run Ruff linter
run: |
cd python/sdk
ruff check .
- name: Run mypy
run: |
cd python/sdk
mypy src/mcp_ext_variants --ignore-missing-imports

python-test:
name: "Unit Tests"
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
cd python/sdk
pip install -e .
pip install pytest pytest-cov
- name: Run tests
run: |
cd python/sdk
pytest -v --cov=src/mcp_ext_variants
138 changes: 138 additions & 0 deletions .github/workflows/status-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
name: Status Check

# This workflow enforces that all relevant CI checks pass based on which files changed.
# It's the only required status check in branch protection settings.

on:
pull_request:
types: [opened, synchronize, reopened]
workflow_run:
workflows: ["Python CI", "Go CI", "TypeScript CI"]
types: [completed]

permissions:
contents: read
statuses: write
checks: write
pull-requests: read

jobs:
verify-required-checks:
name: Verify Required Checks
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event.workflow_run.conclusion != 'cancelled'
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Get PR number
id: pr
run: |
if [ "${{ github.event_name }}" == "workflow_run" ]; then
PR_NUMBER=$(gh pr list --head "${{ github.event.workflow_run.head_branch }}" --json number --jq '.[0].number')
echo "number=$PR_NUMBER" >> $GITHUB_OUTPUT
else
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Get changed files
id: changed-files
uses: dorny/paths-filter@v3
with:
filters: |
python:
- 'python/**'
- '.github/workflows/python.yml'
go:
- 'go/**'
- '.github/workflows/go.yml'
typescript:
- 'typescript/**'
- '.github/workflows/typescript.yml'

- name: Check required statuses
uses: actions/github-script@v7
with:
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const ref = context.payload.pull_request?.head.sha || context.payload.workflow_run?.head_sha;

// Define required checks per language
const requiredChecks = {
python: [
'Python CI / Linting',
'Python CI / Unit Tests (3.10)',
'Python CI / Unit Tests (3.11)',
'Python CI / Unit Tests (3.12)'
],
go: [
'Go CI / Linting',
'Go CI / Unit Tests (1.23)',
'Go CI / Unit Tests (1.24)',
'Go CI / Unit Tests (1.25)',
'Go CI / Race Detection'
],
typescript: [
'TypeScript CI / Linting',
'TypeScript CI / Unit Tests (20)',
'TypeScript CI / Unit Tests (22)'
]
};

// Get changed files from previous step
const changedFiles = {
python: ${{ steps.changed-files.outputs.python }} === 'true',
go: ${{ steps.changed-files.outputs.go }} === 'true',
typescript: ${{ steps.changed-files.outputs.typescript }} === 'true'
};

// Collect all required checks based on changes
let allRequiredChecks = [];
for (const [lang, changed] of Object.entries(changedFiles)) {
if (changed) {
allRequiredChecks = allRequiredChecks.concat(requiredChecks[lang]);
}
}

if (allRequiredChecks.length === 0) {
console.log('No language files changed, no checks required');
return;
}

// Get all check runs for this commit
const { data: checkRuns } = await github.rest.checks.listForRef({
owner,
repo,
ref
});

// Verify all required checks have passed
const checkStatuses = {};
for (const check of checkRuns.check_runs) {
checkStatuses[check.name] = check.conclusion;
}

let allPassed = true;
let failureMessage = '';

for (const requiredCheck of allRequiredChecks) {
const status = checkStatuses[requiredCheck];
if (!status) {
allPassed = false;
failureMessage += `❌ ${requiredCheck}: Not started\\n`;
} else if (status !== 'success') {
allPassed = false;
failureMessage += `❌ ${requiredCheck}: ${status}\\n`;
} else {
failureMessage += `βœ… ${requiredCheck}: ${status}\\n`;
}
}

if (!allPassed) {
core.setFailed(`Required checks have not passed:\\n${failureMessage}`);
} else {
console.log(`All required checks passed:\\n${failureMessage}`);
}
Loading
Loading