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
153 changes: 153 additions & 0 deletions .github/workflows/sweep-open-prs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
name: Sweep Open Codex Plugin Contributions

on:
pull_request_target:
types:
- opened
- synchronize
- reopened
- ready_for_review
schedule:
- cron: "17 3 * * *"
workflow_dispatch:
inputs:
pr_number:
description: "Optional open PR number; omit to sweep every open PR"
required: false
type: string

permissions:
contents: read
pull-requests: read

jobs:
discover:
name: Validate open contribution requirements
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.export.outputs.matrix }}
has_failures: ${{ steps.export.outputs.has_failures }}
results: ${{ steps.export.outputs.results }}
steps:
- name: Check out validator
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.repository.default_branch }}
fetch-depth: 1
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Install validator dependencies
run: python3 -m pip install --disable-pip-version-check --no-input "PyYAML==6.0.2"
- name: Validate open PRs
env:
GITHUB_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number || inputs.pr_number }}
MATRIX_FILE: ${{ runner.temp }}/open-pr-matrix.json
REPORT_FILE: ${{ runner.temp }}/open-pr-report.md
STATUS_FILE: ${{ runner.temp }}/open-pr-status.json
run: |
validator_args=(
--open-prs
--repository "$GITHUB_REPOSITORY"
--matrix-output "$MATRIX_FILE"
--report-output "$REPORT_FILE"
--status-output "$STATUS_FILE"
)
if [[ -n "$PR_NUMBER" ]]; then
validator_args+=(--pr-number "$PR_NUMBER")
fi
python3 scripts/validate-contribution.py "${validator_args[@]}"
- name: Export validation results
id: export
env:
MATRIX_FILE: ${{ runner.temp }}/open-pr-matrix.json
STATUS_FILE: ${{ runner.temp }}/open-pr-status.json
run: |
echo "matrix=$(cat \"$MATRIX_FILE\")" >> "$GITHUB_OUTPUT"
echo "has_failures=$(jq -r '.has_failures' \"$STATUS_FILE\")" >> "$GITHUB_OUTPUT"
echo "results=$(jq -c '.results' \"$STATUS_FILE\")" >> "$GITHUB_OUTPUT"
Comment on lines +68 to +70

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove backslashes around output-file variables

When either workflow reaches its export step, \"$MATRIX_FILE\" is parsed inside the command substitution as literal quote characters, so cat looks for a path named "/.../open-pr-matrix.json" rather than the generated file. The surrounding echo still succeeds and exports an empty matrix; fromJSON('') then prevents the scan matrix from being instantiated, while the two jq calls here also lose the validation status and per-PR results. Use normal nested quoting such as $(cat "$MATRIX_FILE"); the same defect is present in .github/workflows/validate-contribution.yml.

Useful? React with 👍 / 👎.


scan:
name: Scan PR #${{ matrix.contribution.pr_number }} source
needs: discover
if: needs.discover.outputs.matrix != '[]'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
contribution: ${{ fromJSON(needs.discover.outputs.matrix) }}
steps:
- name: Check out contributed repository
env:
CONTRIBUTION_URL: https://github.com/${{ matrix.contribution.owner }}/${{ matrix.contribution.repo }}.git
run: git clone --depth 1 "$CONTRIBUTION_URL" "$RUNNER_TEMP/contributed"
- name: Run HOL AI Plugin Scanner
uses: hashgraph-online/ai-plugin-scanner-action@55616c962cf86368423f7673b2ecdfdbe613d1af # v1.2.515
with:
plugin_dir: ${{ runner.temp }}/contributed
mode: scan
min_score: 80
fail_on_severity: high
pr_comment: off

gate:
name: Open Codex contribution gate
needs:
- discover
- scan
if: always()
runs-on: ubuntu-latest
steps:
- name: Report sweep result
env:
DISCOVER_RESULT: ${{ needs.discover.result }}
HAS_VALIDATION_FAILURES: ${{ needs.discover.outputs.has_failures }}
SCAN_RESULT: ${{ needs.scan.result }}
run: |
if [[ "$DISCOVER_RESULT" != "success" ]]; then
echo "Open-PR discovery failed."
exit 1
fi
if [[ "$HAS_VALIDATION_FAILURES" == "true" ]]; then
echo "One or more open contributions are missing required scanner CI."
exit 1
fi
if [[ "$SCAN_RESULT" != "success" && "$SCAN_RESULT" != "skipped" ]]; then
echo "One or more source-repository scanner jobs failed."
exit 1
fi
echo "All checked open contributions satisfy the scanner gate."

publish:
name: Publish per-PR contribution checks
needs:
- discover
- scan
- gate
if: always()
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
issues: write
pull-requests: write
steps:
- name: Check out validator
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.repository.default_branch }}
fetch-depth: 1
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Publish checks on PR heads
env:
GITHUB_TOKEN: ${{ github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_RUN_ID: ${{ github.run_id }}
OPEN_PR_RESULTS: ${{ needs.discover.outputs.results || '[]' }}
SWEEP_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: python3 scripts/publish-open-pr-checks.py
70 changes: 70 additions & 0 deletions .github/workflows/validate-contribution.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Validate Codex Plugin Contributions

on:
pull_request:
paths:
- "README.md"
- "CONTRIBUTING.md"
- "SCANNER_GUIDE.md"
- "scripts/check-alphabetical.py"
- "scripts/validate-contribution.py"
- ".github/workflows/validate-contribution.yml"
workflow_dispatch:

permissions:
contents: read

jobs:
validate:
name: Check contribution requirements
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.entries.outputs.matrix }}
steps:
- name: Check out catalog
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Install validator dependencies
run: python3 -m pip install --disable-pip-version-check --no-input "PyYAML==6.0.2"
- name: Validate changed entries and source scanner CI
env:
BASE_REF: ${{ github.event_name == 'pull_request' && format('origin/{0}', github.base_ref) || 'origin/main' }}
GITHUB_TOKEN: ${{ github.token }}
run: |
python3 scripts/check-alphabetical.py README.md
python3 scripts/validate-contribution.py \
--base-ref "$BASE_REF" \
--matrix-output "$RUNNER_TEMP/contributions.json"
- name: Export scanner matrix
id: entries
env:
MATRIX_FILE: ${{ runner.temp }}/contributions.json
run: echo "matrix=$(cat \"$MATRIX_FILE\")" >> "$GITHUB_OUTPUT"

scan:
name: Scan ${{ matrix.contribution.owner }}/${{ matrix.contribution.repo }}
needs: validate
if: needs.validate.outputs.matrix != '[]'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
contribution: ${{ fromJSON(needs.validate.outputs.matrix) }}
steps:
- name: Check out contributed repository
env:
CONTRIBUTION_URL: https://github.com/${{ matrix.contribution.owner }}/${{ matrix.contribution.repo }}.git
run: git clone --depth 1 "$CONTRIBUTION_URL" "$RUNNER_TEMP/contributed"
- name: Run HOL AI Plugin Scanner
uses: hashgraph-online/ai-plugin-scanner-action@55616c962cf86368423f7673b2ecdfdbe613d1af # v1.2.515
with:
plugin_dir: ${{ runner.temp }}/contributed
mode: scan
min_score: 80
fail_on_severity: high
pr_comment: off
15 changes: 13 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,24 @@ Before submitting, verify:

## CI Checks

All PRs to this repo are automatically validated. The CI will check:
All PRs to this repo are automatically validated. The contribution gate runs
on the PR target event, so fork PRs do not wait for first-time workflow
approval. It checks the source repository and publishes one status check on
the PR head. When a requirement is missing, the gate updates one idempotent
comment, tags the PR author, and includes the exact scanner workflow and
remediation steps. The check is re-run on every push, reopen, and daily sweep.

The CI will check:

1. **Alphabetical order** - README entries must be sorted within each section
2. **Plugin manifest** - For new README entries, the generator fetches your source repo and validates `plugin.json`, required fields, and icon presence
3. **Scanner verification** - PR description must include scanner score or CI link
3. **Scanner verification** - The source repo must invoke `hashgraph-online/ai-plugin-scanner-action` on `push` or `pull_request`, and the gate runs the scanner at the documented score/severity thresholds
4. **Markdown links** - All URLs in README must be reachable

If the gate comments on your PR, fix the linked source repository first, push
the change there, then update the README PR if needed. The status check and
comment will refresh automatically; do not post duplicate remediation comments.

## Getting Help

- Scanner docs: [HOL Guard](https://github.com/hashgraph-online/hol-guard)
Expand Down
Loading
Loading