Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create GitHub Actions workflows for CI, automation, or PR management. Use when asked to create, scaffold, or add a GitHub Actions workflow (.yml file under .github/workflows/).
.claude/skills/make-github-actions-workflow/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-17 | ✗→✓ | ▲ Improved | — | — |
| case-02 | ✗→✓ | ▲ Improved | — | — |
| case-03 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-04 | ✗→✓ | ▲ Improved | — | — |
Create and configure GitHub Actions workflows that follow this repository's conventions and patterns. Workflows automate tasks like CI validation, PR management, issue labeling, and notifications.
This repository uses specific patterns across all workflows. Follow these conventions when creating new workflows:
.github/workflows/label-and-milestone-issues.yml, validate-pr-target-branch.ymlubuntu-latest for general-purpose jobsubuntu-24.04 when a specific OS version is needed (e.g., copilot setup steps)permissions: {}pull-requests: writeissues: writecontents: readpull_request_target instead of pull_requestpull_request_target workflows run in the base repository context with its permissions. Do not check out or execute code from the PR branch in these workflows. Instead, use the event payload and/or GitHub API (actions/github-script, github.rest.*, etc.) to inspect and act on the PR safely.actions/github-script@v8 for complex logic instead of shell scriptsasync/await — the github object (Octokit) and context are availablegithub.rest.* for REST API calls and github.graphql() for GraphQL queriescontext.payload.pull_request, context.repo.owner, context.repo.repoconsole.log() for debugging; use core.setFailed() for errorsBefore writing the workflow, clarify:
| Use case | Event | Notes | |----------|-------|-------| | PR opened/updated | pull_request | Read-only access to PR | | PR with write access | pull_request_target | Can comment, label, close | | PR merged | pull_request_target: [closed] | Check github.event.pull_request.merged == true | | CI checks complete | check_suite: [completed] | Filter app.slug != 'github-actions' to skip self | | Code pushed | push | Filter by branches/paths | | Manual trigger | workflow_dispatch | Add inputs: for parameters | | Scheduled | schedule | Use cron syntax |
Create the YAML file following this template:
yaml# Description of what this workflow does and why. name: Descriptive Workflow Name on: <trigger_event>: types: [<event_types>] permissions: <resource>: <read|write> jobs: <job-name>: if: <guard_condition> # Optional: skip when not needed runs-on: ubuntu-latest steps: - name: Descriptive step name uses: actions/github-script@v8 with: script: | // Your logic here
Add conditions to avoid unnecessary runs:
if: for event payload checks (e.g., github.event.check_suite.app.slug != 'github-actions')return in scripts for PR author, draft status, etc.After creating the workflow:
actions/github-script@v8 for complex logicper_page: 100)Study these workflows as reference:
| Workflow | Trigger | Purpose | |----------|---------|---------| | validate-pr-target-branch.yml | pull_request_target: [opened, edited, reopened] | Closes external PRs targeting release branches, adds community labels | | label-and-milestone-issues.yml | pull_request_target: [closed] | Labels and milestones issues when their fixing PR is merged | | copilot-setup-steps.yml | workflow_dispatch, push, pull_request | Sets up the development environment for Copilot | | inter-branch-merge-flow.yml | push to release/** | Triggers inter-branch merge via arcade |
javascriptawait github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber, body: 'Comment text' });
javascriptconst { data: permissions } = await github.rest.repos.getCollaboratorPermissionLevel({ owner: context.repo.owner, repo: context.repo.repo, username: context.actor }); const hasWriteAccess = ['admin', 'write'].includes(permissions.permission);
javascriptconst shaTag = `<!-- tag: ${headSha} -->`; const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber, per_page: 100 }); if (comments.some(c => c.body?.includes(shaTag))) { console.log('Already processed'); return; }
javascriptconst { data: fileData } = await github.rest.repos.getContent({ owner, repo, path: 'eng/Versions.props', ref: commitSha }); const content = Buffer.from(fileData.content, 'base64').toString('utf-8');
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-23 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +26 percentage points is the difference between those two pass rates over the 23 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.