Skip to content

PR Checks

PR Checks #16

Workflow file for this run

name: PR Checks
on:
issue_comment:
types: [created]
jobs:
slash-command:
name: Parse /run-checks
if: >-
github.event.issue.pull_request != null &&
contains(github.event.comment.body, '/run-checks')
runs-on: ubuntu-latest
outputs:
pr-sha: ${{ steps.get-sha.outputs.sha }}
steps:
- name: Check commenter permission
uses: actions/github-script@v9
with:
script: |
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: context.actor,
});
if (!['admin', 'write'].includes(data.permission)) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `@${context.actor} Only maintainers can trigger checks.`,
});
core.setFailed('Unauthorized');
}
- name: React with rocket
uses: actions/github-script@v9
with:
script: |
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: ${{ github.event.comment.id }},
content: 'rocket',
});
- name: Get PR head SHA
id: get-sha
uses: actions/github-script@v9
with:
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
});
core.setOutput('sha', pr.head.sha);
- name: Set checks to pending
uses: actions/github-script@v9
with:
script: |
const sha = '${{ steps.get-sha.outputs.sha }}';
const checks = ['Lint', 'Build C++ (ubuntu-22.04)', 'Build C++ (ubuntu-24.04)', 'Build C++ (macos-14)', 'Validate'];
for (const check of checks) {
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha,
state: 'pending',
context: check,
description: 'Waiting...',
});
}
lint:
name: Lint
needs: slash-command
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.slash-command.outputs.pr-sha }}
- name: C++ format check
run: |
sudo apt-get install -y clang-format
find . -name "*.cpp" -o -name "*.h" | grep -v "build/" | \
xargs clang-format --dry-run --Werror || true
- name: Python lint (ruff)
uses: chartboost/ruff-action@v1
with:
args: "check engine/ --ignore E501 --exit-zero"
- name: Report status
if: always()
uses: actions/github-script@v9
with:
script: |
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: '${{ needs.slash-command.outputs.pr-sha }}',
state: '${{ job.status }}' === 'success' ? 'success' : 'failure',
context: 'Lint',
description: '${{ job.status }}',
});
build-cpp:
name: Build C++ (${{ matrix.os }})
needs: slash-command
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-24.04, macos-14]
include:
- os: ubuntu-22.04
artifact: quadtrix-linux-x64
- os: ubuntu-24.04
artifact: quadtrix-linux-x64-noble
- os: macos-14
artifact: quadtrix-macos-arm64
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.slash-command.outputs.pr-sha }}
- name: Install GCC (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y g++ ccache
- name: Cache ccache
uses: actions/cache@v4
with:
path: ~/.ccache
key: ccache-${{ matrix.os }}-${{ hashFiles('**/*.cpp', '**/*.h') }}
restore-keys: ccache-${{ matrix.os }}-
- name: Compile main.cpp
run: |
g++ -std=c++17 -O3 -march=native \
-I. -Iinclude \
-o quadtrix main.cpp
- name: Smoke test
run: ./quadtrix --help || true
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: quadtrix
retention-days: 7
- name: Report status
if: always()
uses: actions/github-script@v9
with:
script: |
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: '${{ needs.slash-command.outputs.pr-sha }}',
state: '${{ job.status }}' === 'success' ? 'success' : 'failure',
context: 'Build C++ (${{ matrix.os }})',
description: '${{ job.status }}',
});
validate:
name: Validate
needs: slash-command
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.slash-command.outputs.pr-sha }}
- name: Check required files exist
run: |
files=(
"main.cpp"
"engine/main.py"
"requirements.txt"
)
failed=0
for f in "${files[@]}"; do
if [ -f "$f" ]; then
echo "✅ $f"
else
echo "❌ $f — MISSING"
failed=1
fi
done
exit $failed
- name: Lint — Dockerfile.cpp
uses: hadolint/hadolint-action@v3.1.0
with:
dockerfile: .devops/Dockerfile.cpp
failure-threshold: error
- name: Lint — Dockerfile (CPU)
uses: hadolint/hadolint-action@v3.1.0
with:
dockerfile: .devops/Dockerfile
failure-threshold: error
- name: Lint — Dockerfile.backend (CUDA)
uses: hadolint/hadolint-action@v3.1.0
with:
dockerfile: .devops/Dockerfile.backend
failure-threshold: error
- name: Report status
if: always()
uses: actions/github-script@v9
with:
script: |
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: '${{ needs.slash-command.outputs.pr-sha }}',
state: '${{ job.status }}' === 'success' ? 'success' : 'failure',
context: 'Validate',
description: '${{ job.status }}',
});
post-result:
name: Post result
needs: [slash-command, lint, build-cpp, validate]
runs-on: ubuntu-latest
if: always()
steps:
- uses: actions/github-script@v9
with:
script: |
const jobs = ${{ toJSON(needs) }};
const failed = Object.values(jobs).some(j => j.result === 'failure');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: failed
? '❌ Some checks failed — see Actions for details.'
: '✅ All checks passed!',
});