Skip to content

Challenge Creation Cron #30

Challenge Creation Cron

Challenge Creation Cron #30

name: Challenge Creation Cron
on:
schedule:
- cron: "0 2 * * 2,4,6" # Monday, Wednesday, Friday at 6 PM PST
workflow_dispatch: {} # Allow manual trigger
jobs:
create-challenge:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: |
pip install pre-commit requests websocket-client modular
pre-commit install
- name: Fetch open PRs
id: open-prs
env:
GH_TOKEN: ${{ github.token }}
run: |
{
echo "open_prs<<OPEN_PRS_EOF"
gh pr list --state open --json number,title,headRefName --template '{{range .}}PR #{{.number}}: {{.title}} (branch: {{.headRefName}}){{"\n"}}{{end}}'
echo "OPEN_PRS_EOF"
} >> "$GITHUB_OUTPUT"
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
env:
SERVICE_URL: ${{ secrets.LEETGPU_SERVICE_URL }}
LEETGPU_API_KEY: ${{ secrets.LEETGPU_API_KEY }}
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
claude_args: "--model claude-sonnet-4-6"
settings: |
{
"permissions": {
"allow": ["Bash", "Read", "Write", "Edit", "Glob", "Grep", "WebFetch", "WebSearch", "Task"]
}
}
prompt: |
Read CLAUDE.md and follow the Creation Workflow to create and validate (with `run_challenge.py`) a new LeetGPU coding challenge, then open a PR.
Before writing any code, think hard about what would make a genuinely interesting GPU programming challenge. List existing challenges (ls challenges/*/), study what's already covered, and brainstorm problems that would teach people something new about GPU programming.
IMPORTANT — CHECK FOR CONFLICTS WITH OPEN PRs:
The following open PRs already exist. You MUST avoid picking a challenge number or topic that conflicts with any of these:
${{ steps.open-prs.outputs.open_prs }}
Pick the next available challenge number that is NOT already taken by a merged challenge or an open PR. Also avoid creating a challenge on the same topic as any pending PR, even if the number differs.
THEME — REAL-WORLD INFERENCE KERNELS:
Focus on challenges inspired by real-world ML inference workloads. Think about the building blocks of modern neural networks (transformers, diffusion models, LLMs, vision models) and the GPU kernels that make them fast. Good examples:
- Fused inference kernels: fused SwiGLU/GeGLU MLP blocks, flash attention, paged attention, speculative decoding verification, quantized matmul (INT8/INT4), fused QKV projection, KV-cache updates
- Sequence/token operations: top-k/top-p sampling, beam search step, KV-cache rotation, causal masking
- Model architecture blocks: full transformer decoder block (like the existing GPT-2 challenge), mixture-of-experts routing, LoRA forward pass
- Online/streaming algorithms: online softmax, streaming attention (process new queries without storing entire rows), continuous batching, prefix caching
Look at `challenges/medium/74_gpt2_block/` as the gold standard for this style of challenge. The solver should implement a meaningful, self-contained inference building block — not a toy operation.
HARD RULES:
- Do NOT create trivial element-wise challenges. We have way too many (sigmoid, relu, silu, clipping, etc). If your idea is just "apply f(x) to every element", pick something else.
- Do NOT duplicate existing challenges — check both the merged challenges in the repo AND the open PRs listed above.
- Do NOT use a challenge number that is already claimed by an open PR.
- Prefer medium or hard difficulty. Only create easy if the topic involves a non-trivial GPU concept (not just a map operation).
- The challenge should require the solver to think about memory access patterns, synchronization, work distribution, or algorithm design — not just write a one-line kernel.
Before opening the PR, verify every item in the "Checklist" section of CLAUDE.md. Run `pre-commit run --all-files` to lint.
- name: Render challenge.html preview
if: steps.claude.outputs.branch_name != ''
run: |
git checkout "${{ steps.claude.outputs.branch_name }}"
git pull origin "${{ steps.claude.outputs.branch_name }}"
CHALLENGE_HTML=$(git diff --name-only origin/main..HEAD -- 'challenges/**/challenge.html' | head -1)
if [ -z "$CHALLENGE_HTML" ]; then
echo "No challenge.html found in diff, skipping render"
exit 0
fi
echo "Rendering $CHALLENGE_HTML"
npm install playwright
npx playwright install --with-deps chromium
node .github/scripts/render-challenge.js "$CHALLENGE_HTML" /tmp/challenge-preview.png
echo "challenge_html=$CHALLENGE_HTML" >> "$GITHUB_ENV"
- name: Commit preview and comment on PR
if: env.challenge_html != ''
env:
GH_TOKEN: ${{ github.token }}
run: |
BRANCH="${{ steps.claude.outputs.branch_name }}"
PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number')
if [ -z "$PR_NUMBER" ]; then
echo "No PR found for branch $BRANCH, skipping"
exit 0
fi
CHALLENGE_DIR=$(dirname "${{ env.challenge_html }}")
PREVIEW_PATH="${CHALLENGE_DIR}/preview.png"
cp /tmp/challenge-preview.png "$PREVIEW_PATH"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add "$PREVIEW_PATH"
git commit -m "Add challenge.html preview image"
git push
REPO="${{ github.repository }}"
SHA=$(git rev-parse HEAD)
IMG_URL="https://raw.githubusercontent.com/${REPO}/${SHA}/${PREVIEW_PATH}"
BODY=$(cat <<EOF
## Challenge Preview
![challenge-preview](${IMG_URL})
EOF
)
gh pr comment "$PR_NUMBER" --body "$BODY"