From 6cad19141db0f2c91e8670ba7308834c83a7c784 Mon Sep 17 00:00:00 2001 From: openhands Date: Wed, 18 Feb 2026 21:03:10 +0000 Subject: [PATCH 1/8] feat: add GitHub Actions skill for workflow creation and debugging - Add comprehensive GitHub Actions skill with SKILL.md - Include practical examples for testing, debugging, and best practices - Cover common pitfalls like action deployment requirements and permissions - Add README.md with detailed scenarios and use cases - Register skill in marketplace.json Closes #55 Co-authored-by: openhands --- .plugin/marketplace.json | 13 + skills/github-actions/README.md | 284 +++++++++++++++++ skills/github-actions/SKILL.md | 530 ++++++++++++++++++++++++++++++++ 3 files changed, 827 insertions(+) create mode 100644 skills/github-actions/README.md create mode 100644 skills/github-actions/SKILL.md diff --git a/.plugin/marketplace.json b/.plugin/marketplace.json index 7118f6d9..c6e87989 100644 --- a/.plugin/marketplace.json +++ b/.plugin/marketplace.json @@ -166,6 +166,19 @@ "workflows" ] }, + { + "name": "github-actions", + "source": "./github-actions", + "description": "Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions.", + "category": "integration", + "keywords": [ + "github-actions", + "workflows", + "ci-cd", + "automation", + "actions" + ] + }, { "name": "github-pr-review", "source": "./github-pr-review", diff --git a/skills/github-actions/README.md b/skills/github-actions/README.md new file mode 100644 index 00000000..9f20a5a9 --- /dev/null +++ b/skills/github-actions/README.md @@ -0,0 +1,284 @@ +# GitHub Actions Skill + +A comprehensive skill for creating, debugging, and testing GitHub Actions workflows and custom actions. + +## Overview + +This skill provides guidance for working with GitHub Actions, including: +- Creating and structuring workflows +- Building custom actions (composite and reusable) +- Testing actions locally and in CI +- Debugging failed workflows +- Avoiding common pitfalls +- Best practices and security considerations + +## When to Use This Skill + +Use this skill when: +- Creating new GitHub Actions workflows +- Building custom composite or reusable actions +- Debugging workflow failures +- Setting up CI/CD pipelines +- Troubleshooting permission or secret issues +- Testing actions before merging to main + +## Key Concepts + +### Action Testing Requirements + +**Critical**: When creating a custom action from scratch: +1. The action **must** be merged to the main branch before it can be used +2. After the initial merge, you can test changes from feature branches +3. Always add debug steps for new or complex actions + +### Types of Actions + +1. **Workflows** (`.github/workflows/*.yml`) - Standard CI/CD pipelines +2. **Composite Actions** (`.github/actions/*/action.yml`) - Reusable actions within a repo +3. **Reusable Workflows** - Workflows that can be called from other workflows + +## Common Scenarios + +### Scenario 1: Creating a New Custom Action + +```bash +# 1. Create the action locally +mkdir -p .github/actions/my-action +cat > .github/actions/my-action/action.yml << 'EOF' +name: My Action +description: Does something useful +inputs: + param: + description: A parameter + required: true +runs: + using: composite + steps: + - run: echo "Param: ${{ inputs.param }}" + shell: bash +EOF + +# 2. Create a workflow to test it +cat > .github/workflows/test-action.yml << 'EOF' +name: Test My Action +on: [push] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/my-action + with: + param: test-value +EOF + +# 3. Commit and merge to main FIRST +git add .github/actions/my-action .github/workflows/test-action.yml +git commit -m "Add custom action" +git push origin feature-branch +# Create and merge PR to main + +# 4. Now you can test changes from other branches +``` + +### Scenario 2: Debugging a Failed Workflow + +```yaml +name: Debug Workflow +on: [push] +jobs: + debug: + runs-on: ubuntu-latest + steps: + # Add debug step at the beginning + - name: Debug - Print all contexts + run: | + echo "Event: ${{ github.event_name }}" + echo "Ref: ${{ github.ref }}" + echo "SHA: ${{ github.sha }}" + echo "Actor: ${{ github.actor }}" + echo "Working dir: $(pwd)" + echo "Environment vars:" + env | sort + + - uses: actions/checkout@v4 + + - name: Debug - Check files + run: ls -la + + # Your actual steps here +``` + +### Scenario 3: Testing Locally with act + +```bash +# Install act +curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash + +# Test the default push event +act + +# Test a specific workflow +act -W .github/workflows/test.yml + +# Test with secrets +act --secret GITHUB_TOKEN=$GITHUB_TOKEN + +# List all jobs that would run +act -l + +# Dry run (show what would execute) +act -n +``` + +### Scenario 4: Handling Permissions Issues + +```yaml +name: PR Comment Workflow +on: + pull_request: + branches: [main] + +jobs: + comment: + runs-on: ubuntu-latest + # Explicitly grant permissions + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v4 + + - name: Comment on PR + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '✅ Validation passed!' + }) +``` + +## Common Pitfalls + +### 1. Forgetting to Merge Action to Main First + +**Problem**: Creating an action and trying to use it before merging to main. + +**Solution**: Always merge the action to the default branch first, then test changes from feature branches. + +### 2. Secrets Not Available in Fork PRs + +**Problem**: Workflows triggered by PRs from forks can't access secrets. + +**Solution**: Don't rely on secrets for fork PR validation, or use `pull_request_target` with caution (security risk). + +### 3. Using Unstable Action References + +**Problem**: Using `@main` or `@master` for action versions can break unexpectedly. + +**Solution**: Pin to specific versions (`@v4`) or SHA hashes. + +### 4. Missing Permissions + +**Problem**: GITHUB_TOKEN doesn't have permissions for operations like commenting on PRs. + +**Solution**: Explicitly declare required permissions in the workflow. + +### 5. Not Printing Debug Information + +**Problem**: Workflows fail without enough context to debug. + +**Solution**: Add a debug step that prints non-secret parameters at the start of your action. + +## Advanced Patterns + +### Reusable Workflow with Matrix + +```yaml +# .github/workflows/reusable-test.yml +name: Reusable Test +on: + workflow_call: + inputs: + node-version: + required: true + type: string + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + - run: npm test + +# Caller workflow +# .github/workflows/ci.yml +name: CI +on: [push] +jobs: + test: + strategy: + matrix: + node-version: [16, 18, 20] + uses: ./.github/workflows/reusable-test.yml + with: + node-version: ${{ matrix.node-version }} +``` + +### Conditional Jobs Based on File Changes + +```yaml +name: Smart CI +on: [push] + +jobs: + changes: + runs-on: ubuntu-latest + outputs: + backend: ${{ steps.filter.outputs.backend }} + frontend: ${{ steps.filter.outputs.frontend }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + backend: + - 'backend/**' + frontend: + - 'frontend/**' + + test-backend: + needs: changes + if: needs.changes.outputs.backend == 'true' + runs-on: ubuntu-latest + steps: + - run: echo "Testing backend" + + test-frontend: + needs: changes + if: needs.changes.outputs.frontend == 'true' + runs-on: ubuntu-latest + steps: + - run: echo "Testing frontend" +``` + +## Resources + +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [Workflow Syntax Reference](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) +- [Security Hardening Guide](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions) +- [act - Local Testing](https://github.com/nektos/act) +- [Awesome Actions](https://github.com/sdras/awesome-actions) + +## Related Skills + +- **github** - General GitHub operations, PR management, and API usage +- **github-pr-review** - Posting structured PR reviews +- **docker** - Working with Docker in GitHub Actions workflows diff --git a/skills/github-actions/SKILL.md b/skills/github-actions/SKILL.md new file mode 100644 index 00000000..b9fb8fd3 --- /dev/null +++ b/skills/github-actions/SKILL.md @@ -0,0 +1,530 @@ +--- +name: github-actions +description: Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions. +triggers: +- github actions +- workflow +- ci/cd +- github workflow +--- + +# GitHub Actions Guide + +## Creating and Testing Actions + + +When creating a GitHub Action from scratch or working with complex workflows: +1. **Initial deployment**: At least one version MUST be merged into the main branch before the action can be used +2. **After first merge**: You can test changes from other branches before merging by referencing the branch name in the workflow +3. **Debug step**: Add a debug step that prints non-secret parameters at the beginning of your action to facilitate troubleshooting + + +## Workflow File Structure + +GitHub Actions workflows are defined in `.github/workflows/*.yml` files: + +```yaml +name: My Workflow +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run a script + run: echo "Hello World" +``` + +## Testing Custom Actions + +### Initial Setup (First Deployment) + +For a new custom action, you MUST merge it to main first: + +```bash +# 1. Create your action in .github/actions/my-action/action.yml +# 2. Commit and push to a branch +git add .github/actions/my-action/action.yml +git commit -m "Add custom action" +git push origin feature-branch + +# 3. Create and merge PR to main +# 4. Now the action can be used in workflows +``` + +### Testing Changes Before Merging + +Once your action exists in main, test changes from feature branches: + +```yaml +# In .github/workflows/test.yml +jobs: + test: + runs-on: ubuntu-latest + steps: + # Test local action from current branch + - uses: actions/checkout@v4 + - uses: ./.github/actions/my-action + + # Or test from specific branch + - uses: owner/repo/.github/actions/my-action@feature-branch +``` + +### Add Debug Step for Troubleshooting + +Always add a debug step when creating new actions or debugging complex issues: + +```yaml +jobs: + build: + runs-on: ubuntu-latest + steps: + # Debug step - prints all non-secret inputs/variables + - name: Debug - Print context + run: | + echo "Event name: ${{ github.event_name }}" + echo "Ref: ${{ github.ref }}" + echo "SHA: ${{ github.sha }}" + echo "Actor: ${{ github.actor }}" + echo "Runner OS: ${{ runner.os }}" + echo "Working directory: $(pwd)" + echo "Environment: ${{ github.event.deployment.environment }}" + # Add any custom inputs or variables (DO NOT print secrets) + echo "Input param: ${{ inputs.my-param }}" + + - name: Actual workflow steps + run: echo "Now running actual logic" +``` + +## Types of GitHub Actions + +### 1. Workflow Files (`.github/workflows/*.yml`) + +Standard CI/CD workflows that run on repository events: + +```yaml +name: CI +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npm test +``` + +### 2. Composite Actions (`.github/actions/*/action.yml`) + +Reusable actions within the same repository: + +```yaml +# .github/actions/setup-env/action.yml +name: Setup Environment +description: Setup project dependencies +inputs: + node-version: + description: Node.js version + required: false + default: '18' +runs: + using: composite + steps: + - uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + - run: npm install + shell: bash +``` + +### 3. Reusable Workflows (`.github/workflows/*.yml` with `workflow_call`) + +Workflows that can be called from other workflows: + +```yaml +# .github/workflows/reusable-deploy.yml +name: Reusable Deploy +on: + workflow_call: + inputs: + environment: + required: true + type: string +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - run: echo "Deploying to ${{ inputs.environment }}" +``` + +## Common Pitfalls and Non-Obvious Gotchas + +### 1. Action Must Exist in Default Branch First + +**Problem**: Referencing an action that doesn't exist in the default branch fails. + +**Solution**: Merge action to main before using it in workflows from other branches. + +### 2. Workflow Triggers and Permissions + +**Problem**: Workflows triggered by `pull_request` from forks have limited permissions. + +**Solution**: Use `pull_request_target` carefully (security risk) or separate workflows for forks: + +```yaml +# Safe pattern for fork PRs +on: + pull_request: + # Limited permissions, safe for forks +jobs: + test: + runs-on: ubuntu-latest + permissions: + contents: read # Explicitly set minimal permissions + steps: + - uses: actions/checkout@v4 +``` + +### 3. GITHUB_TOKEN Permissions + +**Problem**: Default `GITHUB_TOKEN` may lack permissions for certain operations. + +**Solution**: Explicitly declare permissions in workflow: + +```yaml +permissions: + contents: write # Push to repository + pull-requests: write # Comment on PRs + issues: write # Update issues + packages: write # Publish packages +``` + +### 4. Matrix Build Context Access + +**Problem**: Matrix variables aren't accessible in job-level `if` conditions. + +**Solution**: Use `strategy` context: + +```yaml +jobs: + test: + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Linux-specific step + if: ${{ matrix.os == 'ubuntu-latest' }} + run: echo "Linux only" +``` + +### 5. Secrets in Pull Requests from Forks + +**Problem**: Secrets aren't available in workflows triggered by fork PRs (security feature). + +**Solution**: Don't rely on secrets for fork PR validation, or use `pull_request_target` with extreme caution: + +```yaml +# CAREFUL: pull_request_target runs in context of base repo +on: + pull_request_target: + # Only use for safe operations, never run untrusted code +``` + +### 6. Workflow File Changes Don't Trigger Themselves + +**Problem**: Pushing workflow file changes doesn't trigger the workflow on that push. + +**Solution**: The workflow runs on the next trigger event, not when the workflow file is added/modified. + +### 7. Path Filters Are OR'd, Not AND'd + +**Problem**: Multiple paths in path filters match ANY, not ALL. + +```yaml +# This triggers if EITHER path matches +on: + push: + paths: + - 'src/**' + - 'tests/**' +``` + +### 8. Action Versions and References + +**Problem**: Using `@main` for action versions can break if the action changes. + +**Solution**: Pin to specific versions or SHA for stability: + +```yaml +# Recommended: Pin to version +- uses: actions/checkout@v4 + +# Or pin to specific SHA for immutability +- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + +# Avoid: Using @main in production +- uses: actions/checkout@main # Can break without warning +``` + +### 9. Environment Variables vs Inputs + +**Problem**: Confusion between workflow-level env vars and action inputs. + +**Solution**: Know the scopes: + +```yaml +env: + # Available to all jobs in workflow + GLOBAL_VAR: value + +jobs: + build: + env: + # Available to all steps in job + JOB_VAR: value + steps: + - name: Step with env + env: + # Only available to this step + STEP_VAR: value + run: echo "$STEP_VAR" +``` + +### 10. Artifact Upload/Download Between Jobs + +**Problem**: Files don't persist between jobs without explicit artifact handling. + +**Solution**: Use artifacts to share data: + +```yaml +jobs: + build: + runs-on: ubuntu-latest + steps: + - run: echo "data" > output.txt + - uses: actions/upload-artifact@v4 + with: + name: my-artifact + path: output.txt + + deploy: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + with: + name: my-artifact + - run: cat output.txt +``` + +## Local Testing with act + +Test workflows locally before pushing: + +```bash +# Install act +curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash + +# Run workflows locally +act # Run default event (push) +act pull_request # Simulate pull_request event +act -l # List available workflows +act -j test # Run specific job + +# Use with secrets +act --secret GITHUB_TOKEN=xxx + +# Use specific event payload +act -e event.json +``` + +**Note**: `act` doesn't perfectly replicate GitHub Actions environment but catches most issues. + +## Debugging Failed Workflows + +### Enable Debug Logging + +Add repository secrets for verbose logging: +- `ACTIONS_STEP_DEBUG`: true (step-level debug) +- `ACTIONS_RUNNER_DEBUG`: true (runner-level debug) + +Or add to workflow: + +```yaml +jobs: + debug: + runs-on: ubuntu-latest + steps: + - name: Enable debug + run: | + echo "ACTIONS_STEP_DEBUG=true" >> $GITHUB_ENV + echo "ACTIONS_RUNNER_DEBUG=true" >> $GITHUB_ENV + + - name: Debug step + run: echo "::debug::This is a debug message" +``` + +### Common Debug Commands + +```yaml +- name: Debug - Show all environment + run: env | sort + +- name: Debug - Show GitHub context + run: echo '${{ toJSON(github) }}' + +- name: Debug - Show runner context + run: echo '${{ toJSON(runner) }}' + +- name: Debug - Check file structure + run: ls -laR + +- name: Debug - Print secrets (masked) + run: | + # Secrets are automatically masked in output + echo "Token length: ${#GITHUB_TOKEN}" + echo "Token (masked): $GITHUB_TOKEN" +``` + +### Using gh CLI in Workflows + +Monitor and interact with workflows using GitHub CLI: + +```bash +# Check workflow runs +gh run list --workflow=ci.yml + +# Watch a specific run +gh run watch + +# Re-run failed jobs +gh run rerun --failed + +# View logs +gh run view --log + +# Check workflow status from PR +gh pr checks --watch +``` + +## Viewing Workflow Runs + +Use GitHub CLI or API to check workflow status: + +```bash +# List recent workflow runs +gh run list --limit 10 + +# View specific run details +gh run view + +# Watch run in progress +gh run watch + +# Download logs +gh run view --log > workflow.log + +# Check status of PR checks +gh pr checks +``` + +## Best Practices + +1. **Pin action versions**: Use specific versions (`@v4`) or SHA hashes, not `@main` +2. **Minimal permissions**: Explicitly set `permissions` to minimum required +3. **Debug steps**: Add parameter printing for new/complex actions +4. **Fail fast**: Use `fail-fast: false` in matrix builds only when needed +5. **Secrets handling**: Never print secrets; they're masked but can be exposed via encoding +6. **Caching**: Use `actions/cache` for dependencies to speed up workflows +7. **Concurrency control**: Use `concurrency` to cancel redundant workflow runs +8. **Timeout limits**: Set `timeout-minutes` to prevent hung jobs + +```yaml +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 10 # Prevent jobs from hanging + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true # Cancel old runs when new ones start +``` + +## Common Workflow Patterns + +### PR Validation + +```yaml +name: PR Validation +on: + pull_request: + branches: [ main ] + +jobs: + validate: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v4 + - name: Run tests + run: npm test + - name: Comment results + uses: actions/github-script@v7 + if: failure() + with: + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '❌ Tests failed!' + }) +``` + +### Conditional Steps + +```yaml +steps: + - name: Only on main branch + if: github.ref == 'refs/heads/main' + run: echo "Main branch" + + - name: Only on success + if: success() + run: echo "Previous steps succeeded" + + - name: Only on failure + if: failure() + run: echo "Something failed" + + - name: Always run (even on failure) + if: always() + run: echo "Cleanup" +``` + +### Environment Deployments + +```yaml +jobs: + deploy: + runs-on: ubuntu-latest + environment: + name: production + url: https://example.com + steps: + - name: Deploy + run: ./deploy.sh +``` + +## Resources + +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [Workflow Syntax Reference](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) +- [GitHub Actions Marketplace](https://github.com/marketplace?type=actions) +- [act - Local Testing Tool](https://github.com/nektos/act) From 0f6041a611cc57da38ddadfbca3c854fdece9b12 Mon Sep 17 00:00:00 2001 From: openhands Date: Wed, 18 Feb 2026 21:23:41 +0000 Subject: [PATCH 2/8] refactor: consolidate critical rules and clarify debug step guidance - Consolidated repetitive content into a single 'Critical Rules' section - Clarified that debug steps should be used for NEW actions OR tricky issues, not always - Removed redundant explanations scattered throughout the document - Updated both SKILL.md and README.md for consistency Addresses feedback from @juanmichelini --- skills/github-actions/README.md | 6 ++-- skills/github-actions/SKILL.md | 60 +++++++++++++++------------------ 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/skills/github-actions/README.md b/skills/github-actions/README.md index 9f20a5a9..55c715c5 100644 --- a/skills/github-actions/README.md +++ b/skills/github-actions/README.md @@ -29,7 +29,7 @@ Use this skill when: **Critical**: When creating a custom action from scratch: 1. The action **must** be merged to the main branch before it can be used 2. After the initial merge, you can test changes from feature branches -3. Always add debug steps for new or complex actions +3. Add debug steps for new actions or when troubleshooting tricky issues ### Types of Actions @@ -189,9 +189,9 @@ jobs: ### 5. Not Printing Debug Information -**Problem**: Workflows fail without enough context to debug. +**Problem**: Complex or new workflows fail without enough context to debug. -**Solution**: Add a debug step that prints non-secret parameters at the start of your action. +**Solution**: When creating new actions or troubleshooting tricky issues, add a debug step that prints non-secret parameters. ## Advanced Patterns diff --git a/skills/github-actions/SKILL.md b/skills/github-actions/SKILL.md index b9fb8fd3..22fad587 100644 --- a/skills/github-actions/SKILL.md +++ b/skills/github-actions/SKILL.md @@ -10,14 +10,18 @@ triggers: # GitHub Actions Guide -## Creating and Testing Actions +## Critical Rules - -When creating a GitHub Action from scratch or working with complex workflows: -1. **Initial deployment**: At least one version MUST be merged into the main branch before the action can be used -2. **After first merge**: You can test changes from other branches before merging by referencing the branch name in the workflow -3. **Debug step**: Add a debug step that prints non-secret parameters at the beginning of your action to facilitate troubleshooting - +**Custom Action Deployment:** +- New custom actions MUST be merged to the main branch before they can be used +- After the initial merge, changes can be tested from feature branches + +**Debug Steps:** +Add debug steps that print non-secret parameters when: +- Creating a new action, OR +- Troubleshooting a particularly tricky issue + +(Not required for every workflow - use when needed) ## Workflow File Structure @@ -42,9 +46,7 @@ jobs: ## Testing Custom Actions -### Initial Setup (First Deployment) - -For a new custom action, you MUST merge it to main first: +### Workflow for New Actions ```bash # 1. Create your action in .github/actions/my-action/action.yml @@ -53,13 +55,13 @@ git add .github/actions/my-action/action.yml git commit -m "Add custom action" git push origin feature-branch -# 3. Create and merge PR to main -# 4. Now the action can be used in workflows +# 3. Create and merge PR to main (required for first deployment) +# 4. Now the action can be used; future changes can be tested from branches ``` -### Testing Changes Before Merging +### Testing from Feature Branches -Once your action exists in main, test changes from feature branches: +After initial merge, test changes before merging: ```yaml # In .github/workflows/test.yml @@ -75,9 +77,9 @@ jobs: - uses: owner/repo/.github/actions/my-action@feature-branch ``` -### Add Debug Step for Troubleshooting +### Debug Step Example -Always add a debug step when creating new actions or debugging complex issues: +When needed (see Critical Rules above), add debug output: ```yaml jobs: @@ -163,13 +165,7 @@ jobs: ## Common Pitfalls and Non-Obvious Gotchas -### 1. Action Must Exist in Default Branch First - -**Problem**: Referencing an action that doesn't exist in the default branch fails. - -**Solution**: Merge action to main before using it in workflows from other branches. - -### 2. Workflow Triggers and Permissions +### 1. Workflow Triggers and Permissions **Problem**: Workflows triggered by `pull_request` from forks have limited permissions. @@ -189,7 +185,7 @@ jobs: - uses: actions/checkout@v4 ``` -### 3. GITHUB_TOKEN Permissions +### 2. GITHUB_TOKEN Permissions **Problem**: Default `GITHUB_TOKEN` may lack permissions for certain operations. @@ -203,7 +199,7 @@ permissions: packages: write # Publish packages ``` -### 4. Matrix Build Context Access +### 3. Matrix Build Context Access **Problem**: Matrix variables aren't accessible in job-level `if` conditions. @@ -222,7 +218,7 @@ jobs: run: echo "Linux only" ``` -### 5. Secrets in Pull Requests from Forks +### 4. Secrets in Pull Requests from Forks **Problem**: Secrets aren't available in workflows triggered by fork PRs (security feature). @@ -235,13 +231,13 @@ on: # Only use for safe operations, never run untrusted code ``` -### 6. Workflow File Changes Don't Trigger Themselves +### 5. Workflow File Changes Don't Trigger Themselves **Problem**: Pushing workflow file changes doesn't trigger the workflow on that push. **Solution**: The workflow runs on the next trigger event, not when the workflow file is added/modified. -### 7. Path Filters Are OR'd, Not AND'd +### 6. Path Filters Are OR'd, Not AND'd **Problem**: Multiple paths in path filters match ANY, not ALL. @@ -254,7 +250,7 @@ on: - 'tests/**' ``` -### 8. Action Versions and References +### 7. Action Versions and References **Problem**: Using `@main` for action versions can break if the action changes. @@ -271,7 +267,7 @@ on: - uses: actions/checkout@main # Can break without warning ``` -### 9. Environment Variables vs Inputs +### 8. Environment Variables vs Inputs **Problem**: Confusion between workflow-level env vars and action inputs. @@ -295,7 +291,7 @@ jobs: run: echo "$STEP_VAR" ``` -### 10. Artifact Upload/Download Between Jobs +### 9. Artifact Upload/Download Between Jobs **Problem**: Files don't persist between jobs without explicit artifact handling. @@ -437,7 +433,7 @@ gh pr checks 1. **Pin action versions**: Use specific versions (`@v4`) or SHA hashes, not `@main` 2. **Minimal permissions**: Explicitly set `permissions` to minimum required -3. **Debug steps**: Add parameter printing for new/complex actions +3. **Debug steps**: See Critical Rules section for when to add debug output 4. **Fail fast**: Use `fail-fast: false` in matrix builds only when needed 5. **Secrets handling**: Never print secrets; they're masked but can be exposed via encoding 6. **Caching**: Use `actions/cache` for dependencies to speed up workflows From b32b63c5af6e14f3fb646520c2a0763113aad602 Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 23 Feb 2026 16:40:56 +0000 Subject: [PATCH 3/8] refactor: condense SKILL.md to 81 lines following progressive disclosure - Reduced SKILL.md from 526 to 81 lines (within 50-80 line target) - Kept frontmatter and Critical Rules section (got positive review feedback) - Added concise Quick Patterns section showing 3 action types - Condensed Key Gotchas to 4 most critical issues - Moved detailed content to README.md (examples, debugging, testing, best practices) - Eliminated redundancy between SKILL.md and README.md - README.md now contains comprehensive detailed reference material Addresses reviewer feedback: - Progressive disclosure architecture now properly implemented - SKILL.md is a decision guide, not a reference manual - Reduced context token usage for skill loading - No repeated content between files --- skills/github-actions/README.md | 343 +++++++++++++++++++++- skills/github-actions/SKILL.md | 489 ++------------------------------ 2 files changed, 355 insertions(+), 477 deletions(-) diff --git a/skills/github-actions/README.md b/skills/github-actions/README.md index 55c715c5..8cb1fb33 100644 --- a/skills/github-actions/README.md +++ b/skills/github-actions/README.md @@ -33,9 +33,63 @@ Use this skill when: ### Types of Actions -1. **Workflows** (`.github/workflows/*.yml`) - Standard CI/CD pipelines -2. **Composite Actions** (`.github/actions/*/action.yml`) - Reusable actions within a repo -3. **Reusable Workflows** - Workflows that can be called from other workflows +#### 1. Workflow Files (`.github/workflows/*.yml`) + +Standard CI/CD workflows that run on repository events: + +```yaml +name: CI +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npm test +``` + +#### 2. Composite Actions (`.github/actions/*/action.yml`) + +Reusable actions within the same repository: + +```yaml +# .github/actions/setup-env/action.yml +name: Setup Environment +description: Setup project dependencies +inputs: + node-version: + description: Node.js version + required: false + default: '18' +runs: + using: composite + steps: + - uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + - run: npm install + shell: bash +``` + +#### 3. Reusable Workflows (`.github/workflows/*.yml` with `workflow_call`) + +Workflows that can be called from other workflows: + +```yaml +# .github/workflows/reusable-deploy.yml +name: Reusable Deploy +on: + workflow_call: + inputs: + environment: + required: true + type: string +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - run: echo "Deploying to ${{ inputs.environment }}" +``` ## Common Scenarios @@ -171,27 +225,163 @@ jobs: ### 2. Secrets Not Available in Fork PRs -**Problem**: Workflows triggered by PRs from forks can't access secrets. +**Problem**: Workflows triggered by PRs from forks can't access secrets (security feature). + +**Solution**: Don't rely on secrets for fork PR validation, or use `pull_request_target` with extreme caution: -**Solution**: Don't rely on secrets for fork PR validation, or use `pull_request_target` with caution (security risk). +```yaml +# CAREFUL: pull_request_target runs in context of base repo +on: + pull_request_target: + # Only use for safe operations, never run untrusted code +``` ### 3. Using Unstable Action References **Problem**: Using `@main` or `@master` for action versions can break unexpectedly. -**Solution**: Pin to specific versions (`@v4`) or SHA hashes. +**Solution**: Pin to specific versions (`@v4`) or SHA hashes for stability: -### 4. Missing Permissions +```yaml +# Recommended: Pin to version +- uses: actions/checkout@v4 -**Problem**: GITHUB_TOKEN doesn't have permissions for operations like commenting on PRs. +# Or pin to specific SHA for immutability +- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 -**Solution**: Explicitly declare required permissions in the workflow. +# Avoid: Using @main in production +- uses: actions/checkout@main # Can break without warning +``` + +### 4. Missing GITHUB_TOKEN Permissions + +**Problem**: Default `GITHUB_TOKEN` may lack permissions for certain operations like commenting on PRs. + +**Solution**: Explicitly declare required permissions in workflow: + +```yaml +permissions: + contents: write # Push to repository + pull-requests: write # Comment on PRs + issues: write # Update issues + packages: write # Publish packages +``` ### 5. Not Printing Debug Information **Problem**: Complex or new workflows fail without enough context to debug. -**Solution**: When creating new actions or troubleshooting tricky issues, add a debug step that prints non-secret parameters. +**Solution**: When creating new actions or troubleshooting tricky issues, add a debug step that prints non-secret parameters: + +```yaml +jobs: + build: + runs-on: ubuntu-latest + steps: + # Debug step - prints all non-secret inputs/variables + - name: Debug - Print context + run: | + echo "Event name: ${{ github.event_name }}" + echo "Ref: ${{ github.ref }}" + echo "SHA: ${{ github.sha }}" + echo "Actor: ${{ github.actor }}" + echo "Runner OS: ${{ runner.os }}" + echo "Working directory: $(pwd)" + # Add any custom inputs or variables (DO NOT print secrets) + echo "Input param: ${{ inputs.my-param }}" + + - name: Actual workflow steps + run: echo "Now running actual logic" +``` + +### 6. Workflow File Changes Don't Trigger Themselves + +**Problem**: Pushing workflow file changes doesn't trigger the workflow on that push. + +**Solution**: The workflow runs on the next trigger event after the workflow file is merged, not when the workflow file itself is added/modified. + +### 7. Path Filters Are OR'd, Not AND'd + +**Problem**: Multiple paths in path filters match ANY, not ALL. + +```yaml +# This triggers if EITHER path matches (OR logic) +on: + push: + paths: + - 'src/**' + - 'tests/**' +``` + +### 8. Matrix Build Context Access + +**Problem**: Matrix variables aren't accessible in job-level `if` conditions. + +**Solution**: Use `strategy` context properly: + +```yaml +jobs: + test: + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Linux-specific step + if: ${{ matrix.os == 'ubuntu-latest' }} + run: echo "Linux only" +``` + +### 9. Environment Variables vs Inputs + +**Problem**: Confusion between workflow-level env vars and action inputs. + +**Solution**: Understand the scopes: + +```yaml +env: + # Available to all jobs in workflow + GLOBAL_VAR: value + +jobs: + build: + env: + # Available to all steps in job + JOB_VAR: value + steps: + - name: Step with env + env: + # Only available to this step + STEP_VAR: value + run: echo "$STEP_VAR" +``` + +### 10. Artifacts Don't Persist Between Jobs + +**Problem**: Files don't persist between jobs without explicit artifact handling. + +**Solution**: Use artifacts to share data: + +```yaml +jobs: + build: + runs-on: ubuntu-latest + steps: + - run: echo "data" > output.txt + - uses: actions/upload-artifact@v4 + with: + name: my-artifact + path: output.txt + + deploy: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + with: + name: my-artifact + - run: cat output.txt +``` ## Advanced Patterns @@ -269,6 +459,138 @@ jobs: - run: echo "Testing frontend" ``` +## Local Testing with act + +Test workflows locally before pushing: + +```bash +# Install act +curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash + +# Run workflows locally +act # Run default event (push) +act pull_request # Simulate pull_request event +act -l # List available workflows +act -j test # Run specific job + +# Use with secrets +act --secret GITHUB_TOKEN=xxx + +# Use specific event payload +act -e event.json +``` + +**Note**: `act` doesn't perfectly replicate GitHub Actions environment but catches most issues. + +## Debugging Failed Workflows + +### Enable Debug Logging + +Add repository secrets for verbose logging: +- `ACTIONS_STEP_DEBUG`: true (step-level debug) +- `ACTIONS_RUNNER_DEBUG`: true (runner-level debug) + +Or add to workflow: + +```yaml +jobs: + debug: + runs-on: ubuntu-latest + steps: + - name: Enable debug + run: | + echo "ACTIONS_STEP_DEBUG=true" >> $GITHUB_ENV + echo "ACTIONS_RUNNER_DEBUG=true" >> $GITHUB_ENV + + - name: Debug step + run: echo "::debug::This is a debug message" +``` + +### Common Debug Commands + +```yaml +- name: Debug - Show all environment + run: env | sort + +- name: Debug - Show GitHub context + run: echo '${{ toJSON(github) }}' + +- name: Debug - Show runner context + run: echo '${{ toJSON(runner) }}' + +- name: Debug - Check file structure + run: ls -laR + +- name: Debug - Print secrets (masked) + run: | + # Secrets are automatically masked in output + echo "Token length: ${#GITHUB_TOKEN}" + echo "Token (masked): $GITHUB_TOKEN" +``` + +### Using gh CLI for Workflow Management + +Monitor and interact with workflows using GitHub CLI: + +```bash +# Check workflow runs +gh run list --workflow=ci.yml + +# Watch a specific run +gh run watch + +# Re-run failed jobs +gh run rerun --failed + +# View logs +gh run view --log + +# Check workflow status from PR +gh pr checks --watch + +# List recent workflow runs +gh run list --limit 10 + +# Download logs +gh run view --log > workflow.log +``` + +## Best Practices + +1. **Pin action versions**: Use specific versions (`@v4`) or SHA hashes, not `@main` +2. **Minimal permissions**: Explicitly set `permissions` to minimum required +3. **Debug steps**: Add debug output when creating new actions or troubleshooting tricky issues (not required for every workflow) +4. **Fail fast**: Use `fail-fast: false` in matrix builds only when needed +5. **Secrets handling**: Never print secrets; they're masked but can be exposed via encoding +6. **Caching**: Use `actions/cache` for dependencies to speed up workflows +7. **Concurrency control**: Use `concurrency` to cancel redundant workflow runs +8. **Timeout limits**: Set `timeout-minutes` to prevent hung jobs + +### Example Best Practice Implementation + +```yaml +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 10 # Prevent jobs from hanging + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true # Cancel old runs when new ones start + permissions: + contents: read # Minimal permissions + steps: + - uses: actions/checkout@v4 # Pinned version + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + + - run: npm ci + - run: npm test +``` + ## Resources - [GitHub Actions Documentation](https://docs.github.com/en/actions) @@ -276,6 +598,7 @@ jobs: - [Security Hardening Guide](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions) - [act - Local Testing](https://github.com/nektos/act) - [Awesome Actions](https://github.com/sdras/awesome-actions) +- [GitHub Actions Marketplace](https://github.com/marketplace?type=actions) ## Related Skills diff --git a/skills/github-actions/SKILL.md b/skills/github-actions/SKILL.md index 22fad587..60f36215 100644 --- a/skills/github-actions/SKILL.md +++ b/skills/github-actions/SKILL.md @@ -23,94 +23,11 @@ Add debug steps that print non-secret parameters when: (Not required for every workflow - use when needed) -## Workflow File Structure - -GitHub Actions workflows are defined in `.github/workflows/*.yml` files: - -```yaml -name: My Workflow -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Run a script - run: echo "Hello World" -``` - -## Testing Custom Actions - -### Workflow for New Actions - -```bash -# 1. Create your action in .github/actions/my-action/action.yml -# 2. Commit and push to a branch -git add .github/actions/my-action/action.yml -git commit -m "Add custom action" -git push origin feature-branch - -# 3. Create and merge PR to main (required for first deployment) -# 4. Now the action can be used; future changes can be tested from branches -``` - -### Testing from Feature Branches - -After initial merge, test changes before merging: - -```yaml -# In .github/workflows/test.yml -jobs: - test: - runs-on: ubuntu-latest - steps: - # Test local action from current branch - - uses: actions/checkout@v4 - - uses: ./.github/actions/my-action - - # Or test from specific branch - - uses: owner/repo/.github/actions/my-action@feature-branch -``` - -### Debug Step Example - -When needed (see Critical Rules above), add debug output: +## Quick Patterns +**Basic Workflow:** ```yaml -jobs: - build: - runs-on: ubuntu-latest - steps: - # Debug step - prints all non-secret inputs/variables - - name: Debug - Print context - run: | - echo "Event name: ${{ github.event_name }}" - echo "Ref: ${{ github.ref }}" - echo "SHA: ${{ github.sha }}" - echo "Actor: ${{ github.actor }}" - echo "Runner OS: ${{ runner.os }}" - echo "Working directory: $(pwd)" - echo "Environment: ${{ github.event.deployment.environment }}" - # Add any custom inputs or variables (DO NOT print secrets) - echo "Input param: ${{ inputs.my-param }}" - - - name: Actual workflow steps - run: echo "Now running actual logic" -``` - -## Types of GitHub Actions - -### 1. Workflow Files (`.github/workflows/*.yml`) - -Standard CI/CD workflows that run on repository events: - -```yaml -name: CI +# .github/workflows/ci.yml on: [push, pull_request] jobs: test: @@ -120,407 +37,45 @@ jobs: - run: npm test ``` -### 2. Composite Actions (`.github/actions/*/action.yml`) - -Reusable actions within the same repository: - +**Composite Action:** ```yaml -# .github/actions/setup-env/action.yml -name: Setup Environment -description: Setup project dependencies -inputs: - node-version: - description: Node.js version - required: false - default: '18' +# .github/actions/setup/action.yml +name: Setup runs: using: composite steps: - - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node-version }} - run: npm install shell: bash ``` -### 3. Reusable Workflows (`.github/workflows/*.yml` with `workflow_call`) - -Workflows that can be called from other workflows: - +**Reusable Workflow:** ```yaml -# .github/workflows/reusable-deploy.yml -name: Reusable Deploy +# .github/workflows/deploy.yml on: workflow_call: inputs: - environment: + env: required: true type: string jobs: deploy: runs-on: ubuntu-latest steps: - - run: echo "Deploying to ${{ inputs.environment }}" -``` - -## Common Pitfalls and Non-Obvious Gotchas - -### 1. Workflow Triggers and Permissions - -**Problem**: Workflows triggered by `pull_request` from forks have limited permissions. - -**Solution**: Use `pull_request_target` carefully (security risk) or separate workflows for forks: - -```yaml -# Safe pattern for fork PRs -on: - pull_request: - # Limited permissions, safe for forks -jobs: - test: - runs-on: ubuntu-latest - permissions: - contents: read # Explicitly set minimal permissions - steps: - - uses: actions/checkout@v4 -``` - -### 2. GITHUB_TOKEN Permissions - -**Problem**: Default `GITHUB_TOKEN` may lack permissions for certain operations. - -**Solution**: Explicitly declare permissions in workflow: - -```yaml -permissions: - contents: write # Push to repository - pull-requests: write # Comment on PRs - issues: write # Update issues - packages: write # Publish packages -``` - -### 3. Matrix Build Context Access - -**Problem**: Matrix variables aren't accessible in job-level `if` conditions. - -**Solution**: Use `strategy` context: - -```yaml -jobs: - test: - strategy: - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Linux-specific step - if: ${{ matrix.os == 'ubuntu-latest' }} - run: echo "Linux only" -``` - -### 4. Secrets in Pull Requests from Forks - -**Problem**: Secrets aren't available in workflows triggered by fork PRs (security feature). - -**Solution**: Don't rely on secrets for fork PR validation, or use `pull_request_target` with extreme caution: - -```yaml -# CAREFUL: pull_request_target runs in context of base repo -on: - pull_request_target: - # Only use for safe operations, never run untrusted code -``` - -### 5. Workflow File Changes Don't Trigger Themselves - -**Problem**: Pushing workflow file changes doesn't trigger the workflow on that push. - -**Solution**: The workflow runs on the next trigger event, not when the workflow file is added/modified. - -### 6. Path Filters Are OR'd, Not AND'd - -**Problem**: Multiple paths in path filters match ANY, not ALL. - -```yaml -# This triggers if EITHER path matches -on: - push: - paths: - - 'src/**' - - 'tests/**' -``` - -### 7. Action Versions and References - -**Problem**: Using `@main` for action versions can break if the action changes. - -**Solution**: Pin to specific versions or SHA for stability: - -```yaml -# Recommended: Pin to version -- uses: actions/checkout@v4 - -# Or pin to specific SHA for immutability -- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - -# Avoid: Using @main in production -- uses: actions/checkout@main # Can break without warning + - run: echo "Deploy to ${{ inputs.env }}" ``` -### 8. Environment Variables vs Inputs +## Key Gotchas -**Problem**: Confusion between workflow-level env vars and action inputs. - -**Solution**: Know the scopes: - -```yaml -env: - # Available to all jobs in workflow - GLOBAL_VAR: value - -jobs: - build: - env: - # Available to all steps in job - JOB_VAR: value - steps: - - name: Step with env - env: - # Only available to this step - STEP_VAR: value - run: echo "$STEP_VAR" -``` - -### 9. Artifact Upload/Download Between Jobs - -**Problem**: Files don't persist between jobs without explicit artifact handling. - -**Solution**: Use artifacts to share data: - -```yaml -jobs: - build: - runs-on: ubuntu-latest - steps: - - run: echo "data" > output.txt - - uses: actions/upload-artifact@v4 - with: - name: my-artifact - path: output.txt - - deploy: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/download-artifact@v4 - with: - name: my-artifact - - run: cat output.txt -``` - -## Local Testing with act - -Test workflows locally before pushing: - -```bash -# Install act -curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash - -# Run workflows locally -act # Run default event (push) -act pull_request # Simulate pull_request event -act -l # List available workflows -act -j test # Run specific job - -# Use with secrets -act --secret GITHUB_TOKEN=xxx - -# Use specific event payload -act -e event.json -``` - -**Note**: `act` doesn't perfectly replicate GitHub Actions environment but catches most issues. - -## Debugging Failed Workflows - -### Enable Debug Logging - -Add repository secrets for verbose logging: -- `ACTIONS_STEP_DEBUG`: true (step-level debug) -- `ACTIONS_RUNNER_DEBUG`: true (runner-level debug) - -Or add to workflow: - -```yaml -jobs: - debug: - runs-on: ubuntu-latest - steps: - - name: Enable debug - run: | - echo "ACTIONS_STEP_DEBUG=true" >> $GITHUB_ENV - echo "ACTIONS_RUNNER_DEBUG=true" >> $GITHUB_ENV - - - name: Debug step - run: echo "::debug::This is a debug message" -``` - -### Common Debug Commands - -```yaml -- name: Debug - Show all environment - run: env | sort - -- name: Debug - Show GitHub context - run: echo '${{ toJSON(github) }}' - -- name: Debug - Show runner context - run: echo '${{ toJSON(runner) }}' - -- name: Debug - Check file structure - run: ls -laR - -- name: Debug - Print secrets (masked) - run: | - # Secrets are automatically masked in output - echo "Token length: ${#GITHUB_TOKEN}" - echo "Token (masked): $GITHUB_TOKEN" -``` - -### Using gh CLI in Workflows - -Monitor and interact with workflows using GitHub CLI: - -```bash -# Check workflow runs -gh run list --workflow=ci.yml - -# Watch a specific run -gh run watch - -# Re-run failed jobs -gh run rerun --failed - -# View logs -gh run view --log - -# Check workflow status from PR -gh pr checks --watch -``` - -## Viewing Workflow Runs - -Use GitHub CLI or API to check workflow status: - -```bash -# List recent workflow runs -gh run list --limit 10 - -# View specific run details -gh run view - -# Watch run in progress -gh run watch - -# Download logs -gh run view --log > workflow.log - -# Check status of PR checks -gh pr checks -``` - -## Best Practices - -1. **Pin action versions**: Use specific versions (`@v4`) or SHA hashes, not `@main` -2. **Minimal permissions**: Explicitly set `permissions` to minimum required -3. **Debug steps**: See Critical Rules section for when to add debug output -4. **Fail fast**: Use `fail-fast: false` in matrix builds only when needed -5. **Secrets handling**: Never print secrets; they're masked but can be exposed via encoding -6. **Caching**: Use `actions/cache` for dependencies to speed up workflows -7. **Concurrency control**: Use `concurrency` to cancel redundant workflow runs -8. **Timeout limits**: Set `timeout-minutes` to prevent hung jobs - -```yaml -jobs: - build: - runs-on: ubuntu-latest - timeout-minutes: 10 # Prevent jobs from hanging - concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true # Cancel old runs when new ones start -``` - -## Common Workflow Patterns - -### PR Validation - -```yaml -name: PR Validation -on: - pull_request: - branches: [ main ] - -jobs: - validate: - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - steps: - - uses: actions/checkout@v4 - - name: Run tests - run: npm test - - name: Comment results - uses: actions/github-script@v7 - if: failure() - with: - script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: '❌ Tests failed!' - }) -``` - -### Conditional Steps - -```yaml -steps: - - name: Only on main branch - if: github.ref == 'refs/heads/main' - run: echo "Main branch" - - - name: Only on success - if: success() - run: echo "Previous steps succeeded" - - - name: Only on failure - if: failure() - run: echo "Something failed" - - - name: Always run (even on failure) - if: always() - run: echo "Cleanup" -``` - -### Environment Deployments - -```yaml -jobs: - deploy: - runs-on: ubuntu-latest - environment: - name: production - url: https://example.com - steps: - - name: Deploy - run: ./deploy.sh -``` +1. **Secrets unavailable in fork PRs** - Use `pull_request_target` with caution or don't rely on secrets +2. **Pin action versions** - Use `@v4` or SHA, not `@main` (prevents breaking changes) +3. **Explicit permissions** - Set `permissions:` block for GITHUB_TOKEN operations +4. **Artifacts for job-to-job data** - Files don't persist between jobs without `upload-artifact`/`download-artifact` -## Resources +## Detailed Information -- [GitHub Actions Documentation](https://docs.github.com/en/actions) -- [Workflow Syntax Reference](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) -- [GitHub Actions Marketplace](https://github.com/marketplace?type=actions) -- [act - Local Testing Tool](https://github.com/nektos/act) +See [README.md](README.md) for: +- Step-by-step examples and scenarios +- Complete list of common pitfalls +- Local testing with `act` +- Debugging techniques and `gh` CLI usage +- Advanced patterns and best practices From ecc38a31588e2f17dd73148c7462b111032445fc Mon Sep 17 00:00:00 2001 From: openhands Date: Tue, 3 Mar 2026 00:55:50 +0000 Subject: [PATCH 4/8] refactor: replace Quick Patterns with Testing & Monitoring Strategy - Remove Quick Patterns section (syntax examples moved to README) - Add Testing & Monitoring Strategy focused on effectiveness - Emphasize cost awareness (CI minutes consumption) - Add practical debugging workflow with gh CLI commands - Focus on reading logs and understanding actual behavior vs guessing - Include visibility best practices (debug steps for inputs/outputs) Addresses reviewer feedback to make skill about SWE effectiveness, not syntax. --- skills/github-actions/SKILL.md | 74 ++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/skills/github-actions/SKILL.md b/skills/github-actions/SKILL.md index 60f36215..9b11f4d2 100644 --- a/skills/github-actions/SKILL.md +++ b/skills/github-actions/SKILL.md @@ -23,45 +23,51 @@ Add debug steps that print non-secret parameters when: (Not required for every workflow - use when needed) -## Quick Patterns +## Testing & Monitoring Strategy -**Basic Workflow:** -```yaml -# .github/workflows/ci.yml -on: [push, pull_request] -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: npm test -``` +**Actions have costs** - Each workflow run consumes CI minutes. Plan efficiently: -**Composite Action:** -```yaml -# .github/actions/setup/action.yml -name: Setup -runs: - using: composite - steps: - - run: npm install - shell: bash +1. **Test locally first** with `act` when possible +2. **Use debug steps early** - don't guess, read actual values +3. **Monitor actively** - use `gh run watch ` or `gh pr checks --watch` +4. **Read logs immediately** - `gh run view --log` or view in GitHub UI +5. **Understand before changing** - examine what actually ran, not what you think ran + +**Effective debugging workflow:** +```bash +# Watch workflow run in real-time +gh run watch + +# Or monitor PR checks with auto-refresh +gh pr checks --watch --interval 10 + +# When failed, read full logs immediately +gh run view --log + +# Examine specific job logs +gh run view --log --job= ``` -**Reusable Workflow:** +**Add visibility to your actions:** ```yaml -# .github/workflows/deploy.yml -on: - workflow_call: - inputs: - env: - required: true - type: string -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - run: echo "Deploy to ${{ inputs.env }}" +steps: + # Print all non-secret inputs/context at start + - name: Debug - Action inputs + run: | + echo "Event: ${{ github.event_name }}" + echo "Ref: ${{ github.ref }}" + echo "Actor: ${{ github.actor }}" + echo "Working dir: $(pwd)" + echo "Custom input: ${{ inputs.my-param }}" + + # Your action logic here + + # Verify outcome before finishing + - name: Debug - Verify results + run: | + echo "Files created:" + ls -la + echo "Exit code: $?" ``` ## Key Gotchas From e26df737b0baf0e4ab737ea7102cb5eeaf527941 Mon Sep 17 00:00:00 2001 From: Juan Michelini Date: Tue, 3 Mar 2026 21:19:37 -0300 Subject: [PATCH 5/8] Removed red herrings --- skills/github-actions/SKILL.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/skills/github-actions/SKILL.md b/skills/github-actions/SKILL.md index 9b11f4d2..47140742 100644 --- a/skills/github-actions/SKILL.md +++ b/skills/github-actions/SKILL.md @@ -14,7 +14,7 @@ triggers: **Custom Action Deployment:** - New custom actions MUST be merged to the main branch before they can be used -- After the initial merge, changes can be tested from feature branches +- After the initial merge, should tested from feature branches **Debug Steps:** Add debug steps that print non-secret parameters when: @@ -27,11 +27,10 @@ Add debug steps that print non-secret parameters when: **Actions have costs** - Each workflow run consumes CI minutes. Plan efficiently: -1. **Test locally first** with `act` when possible -2. **Use debug steps early** - don't guess, read actual values -3. **Monitor actively** - use `gh run watch ` or `gh pr checks --watch` -4. **Read logs immediately** - `gh run view --log` or view in GitHub UI -5. **Understand before changing** - examine what actually ran, not what you think ran +1. **Use debug steps early** - don't guess, read actual values +2. **Monitor actively** - use `gh run watch ` or `gh pr checks --watch` +3. **Read logs immediately** - `gh run view --log` or view in GitHub UI +4. **Understand before changing** - examine what actually ran, not what you think ran **Effective debugging workflow:** ```bash @@ -77,11 +76,3 @@ steps: 3. **Explicit permissions** - Set `permissions:` block for GITHUB_TOKEN operations 4. **Artifacts for job-to-job data** - Files don't persist between jobs without `upload-artifact`/`download-artifact` -## Detailed Information - -See [README.md](README.md) for: -- Step-by-step examples and scenarios -- Complete list of common pitfalls -- Local testing with `act` -- Debugging techniques and `gh` CLI usage -- Advanced patterns and best practices From 11f1459ec309444eaeaed40ec1d4d5f65fef3890 Mon Sep 17 00:00:00 2001 From: Juan Michelini Date: Tue, 3 Mar 2026 21:20:35 -0300 Subject: [PATCH 6/8] Refactor GitHub Actions README to remove excess content Removed detailed sections on key concepts, scenarios, common pitfalls, advanced patterns, and best practices from the GitHub Actions README. --- skills/github-actions/README.md | 573 -------------------------------- 1 file changed, 573 deletions(-) diff --git a/skills/github-actions/README.md b/skills/github-actions/README.md index 8cb1fb33..e13d8908 100644 --- a/skills/github-actions/README.md +++ b/skills/github-actions/README.md @@ -22,539 +22,6 @@ Use this skill when: - Troubleshooting permission or secret issues - Testing actions before merging to main -## Key Concepts - -### Action Testing Requirements - -**Critical**: When creating a custom action from scratch: -1. The action **must** be merged to the main branch before it can be used -2. After the initial merge, you can test changes from feature branches -3. Add debug steps for new actions or when troubleshooting tricky issues - -### Types of Actions - -#### 1. Workflow Files (`.github/workflows/*.yml`) - -Standard CI/CD workflows that run on repository events: - -```yaml -name: CI -on: [push, pull_request] -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: npm test -``` - -#### 2. Composite Actions (`.github/actions/*/action.yml`) - -Reusable actions within the same repository: - -```yaml -# .github/actions/setup-env/action.yml -name: Setup Environment -description: Setup project dependencies -inputs: - node-version: - description: Node.js version - required: false - default: '18' -runs: - using: composite - steps: - - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node-version }} - - run: npm install - shell: bash -``` - -#### 3. Reusable Workflows (`.github/workflows/*.yml` with `workflow_call`) - -Workflows that can be called from other workflows: - -```yaml -# .github/workflows/reusable-deploy.yml -name: Reusable Deploy -on: - workflow_call: - inputs: - environment: - required: true - type: string -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - run: echo "Deploying to ${{ inputs.environment }}" -``` - -## Common Scenarios - -### Scenario 1: Creating a New Custom Action - -```bash -# 1. Create the action locally -mkdir -p .github/actions/my-action -cat > .github/actions/my-action/action.yml << 'EOF' -name: My Action -description: Does something useful -inputs: - param: - description: A parameter - required: true -runs: - using: composite - steps: - - run: echo "Param: ${{ inputs.param }}" - shell: bash -EOF - -# 2. Create a workflow to test it -cat > .github/workflows/test-action.yml << 'EOF' -name: Test My Action -on: [push] -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/my-action - with: - param: test-value -EOF - -# 3. Commit and merge to main FIRST -git add .github/actions/my-action .github/workflows/test-action.yml -git commit -m "Add custom action" -git push origin feature-branch -# Create and merge PR to main - -# 4. Now you can test changes from other branches -``` - -### Scenario 2: Debugging a Failed Workflow - -```yaml -name: Debug Workflow -on: [push] -jobs: - debug: - runs-on: ubuntu-latest - steps: - # Add debug step at the beginning - - name: Debug - Print all contexts - run: | - echo "Event: ${{ github.event_name }}" - echo "Ref: ${{ github.ref }}" - echo "SHA: ${{ github.sha }}" - echo "Actor: ${{ github.actor }}" - echo "Working dir: $(pwd)" - echo "Environment vars:" - env | sort - - - uses: actions/checkout@v4 - - - name: Debug - Check files - run: ls -la - - # Your actual steps here -``` - -### Scenario 3: Testing Locally with act - -```bash -# Install act -curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash - -# Test the default push event -act - -# Test a specific workflow -act -W .github/workflows/test.yml - -# Test with secrets -act --secret GITHUB_TOKEN=$GITHUB_TOKEN - -# List all jobs that would run -act -l - -# Dry run (show what would execute) -act -n -``` - -### Scenario 4: Handling Permissions Issues - -```yaml -name: PR Comment Workflow -on: - pull_request: - branches: [main] - -jobs: - comment: - runs-on: ubuntu-latest - # Explicitly grant permissions - permissions: - contents: read - pull-requests: write - steps: - - uses: actions/checkout@v4 - - - name: Comment on PR - uses: actions/github-script@v7 - with: - script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: '✅ Validation passed!' - }) -``` - -## Common Pitfalls - -### 1. Forgetting to Merge Action to Main First - -**Problem**: Creating an action and trying to use it before merging to main. - -**Solution**: Always merge the action to the default branch first, then test changes from feature branches. - -### 2. Secrets Not Available in Fork PRs - -**Problem**: Workflows triggered by PRs from forks can't access secrets (security feature). - -**Solution**: Don't rely on secrets for fork PR validation, or use `pull_request_target` with extreme caution: - -```yaml -# CAREFUL: pull_request_target runs in context of base repo -on: - pull_request_target: - # Only use for safe operations, never run untrusted code -``` - -### 3. Using Unstable Action References - -**Problem**: Using `@main` or `@master` for action versions can break unexpectedly. - -**Solution**: Pin to specific versions (`@v4`) or SHA hashes for stability: - -```yaml -# Recommended: Pin to version -- uses: actions/checkout@v4 - -# Or pin to specific SHA for immutability -- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - -# Avoid: Using @main in production -- uses: actions/checkout@main # Can break without warning -``` - -### 4. Missing GITHUB_TOKEN Permissions - -**Problem**: Default `GITHUB_TOKEN` may lack permissions for certain operations like commenting on PRs. - -**Solution**: Explicitly declare required permissions in workflow: - -```yaml -permissions: - contents: write # Push to repository - pull-requests: write # Comment on PRs - issues: write # Update issues - packages: write # Publish packages -``` - -### 5. Not Printing Debug Information - -**Problem**: Complex or new workflows fail without enough context to debug. - -**Solution**: When creating new actions or troubleshooting tricky issues, add a debug step that prints non-secret parameters: - -```yaml -jobs: - build: - runs-on: ubuntu-latest - steps: - # Debug step - prints all non-secret inputs/variables - - name: Debug - Print context - run: | - echo "Event name: ${{ github.event_name }}" - echo "Ref: ${{ github.ref }}" - echo "SHA: ${{ github.sha }}" - echo "Actor: ${{ github.actor }}" - echo "Runner OS: ${{ runner.os }}" - echo "Working directory: $(pwd)" - # Add any custom inputs or variables (DO NOT print secrets) - echo "Input param: ${{ inputs.my-param }}" - - - name: Actual workflow steps - run: echo "Now running actual logic" -``` - -### 6. Workflow File Changes Don't Trigger Themselves - -**Problem**: Pushing workflow file changes doesn't trigger the workflow on that push. - -**Solution**: The workflow runs on the next trigger event after the workflow file is merged, not when the workflow file itself is added/modified. - -### 7. Path Filters Are OR'd, Not AND'd - -**Problem**: Multiple paths in path filters match ANY, not ALL. - -```yaml -# This triggers if EITHER path matches (OR logic) -on: - push: - paths: - - 'src/**' - - 'tests/**' -``` - -### 8. Matrix Build Context Access - -**Problem**: Matrix variables aren't accessible in job-level `if` conditions. - -**Solution**: Use `strategy` context properly: - -```yaml -jobs: - test: - strategy: - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Linux-specific step - if: ${{ matrix.os == 'ubuntu-latest' }} - run: echo "Linux only" -``` - -### 9. Environment Variables vs Inputs - -**Problem**: Confusion between workflow-level env vars and action inputs. - -**Solution**: Understand the scopes: - -```yaml -env: - # Available to all jobs in workflow - GLOBAL_VAR: value - -jobs: - build: - env: - # Available to all steps in job - JOB_VAR: value - steps: - - name: Step with env - env: - # Only available to this step - STEP_VAR: value - run: echo "$STEP_VAR" -``` - -### 10. Artifacts Don't Persist Between Jobs - -**Problem**: Files don't persist between jobs without explicit artifact handling. - -**Solution**: Use artifacts to share data: - -```yaml -jobs: - build: - runs-on: ubuntu-latest - steps: - - run: echo "data" > output.txt - - uses: actions/upload-artifact@v4 - with: - name: my-artifact - path: output.txt - - deploy: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/download-artifact@v4 - with: - name: my-artifact - - run: cat output.txt -``` - -## Advanced Patterns - -### Reusable Workflow with Matrix - -```yaml -# .github/workflows/reusable-test.yml -name: Reusable Test -on: - workflow_call: - inputs: - node-version: - required: true - type: string - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node-version }} - - run: npm test - -# Caller workflow -# .github/workflows/ci.yml -name: CI -on: [push] -jobs: - test: - strategy: - matrix: - node-version: [16, 18, 20] - uses: ./.github/workflows/reusable-test.yml - with: - node-version: ${{ matrix.node-version }} -``` - -### Conditional Jobs Based on File Changes - -```yaml -name: Smart CI -on: [push] - -jobs: - changes: - runs-on: ubuntu-latest - outputs: - backend: ${{ steps.filter.outputs.backend }} - frontend: ${{ steps.filter.outputs.frontend }} - steps: - - uses: actions/checkout@v4 - - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - backend: - - 'backend/**' - frontend: - - 'frontend/**' - - test-backend: - needs: changes - if: needs.changes.outputs.backend == 'true' - runs-on: ubuntu-latest - steps: - - run: echo "Testing backend" - - test-frontend: - needs: changes - if: needs.changes.outputs.frontend == 'true' - runs-on: ubuntu-latest - steps: - - run: echo "Testing frontend" -``` - -## Local Testing with act - -Test workflows locally before pushing: - -```bash -# Install act -curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash - -# Run workflows locally -act # Run default event (push) -act pull_request # Simulate pull_request event -act -l # List available workflows -act -j test # Run specific job - -# Use with secrets -act --secret GITHUB_TOKEN=xxx - -# Use specific event payload -act -e event.json -``` - -**Note**: `act` doesn't perfectly replicate GitHub Actions environment but catches most issues. - -## Debugging Failed Workflows - -### Enable Debug Logging - -Add repository secrets for verbose logging: -- `ACTIONS_STEP_DEBUG`: true (step-level debug) -- `ACTIONS_RUNNER_DEBUG`: true (runner-level debug) - -Or add to workflow: - -```yaml -jobs: - debug: - runs-on: ubuntu-latest - steps: - - name: Enable debug - run: | - echo "ACTIONS_STEP_DEBUG=true" >> $GITHUB_ENV - echo "ACTIONS_RUNNER_DEBUG=true" >> $GITHUB_ENV - - - name: Debug step - run: echo "::debug::This is a debug message" -``` - -### Common Debug Commands - -```yaml -- name: Debug - Show all environment - run: env | sort - -- name: Debug - Show GitHub context - run: echo '${{ toJSON(github) }}' - -- name: Debug - Show runner context - run: echo '${{ toJSON(runner) }}' - -- name: Debug - Check file structure - run: ls -laR - -- name: Debug - Print secrets (masked) - run: | - # Secrets are automatically masked in output - echo "Token length: ${#GITHUB_TOKEN}" - echo "Token (masked): $GITHUB_TOKEN" -``` - -### Using gh CLI for Workflow Management - -Monitor and interact with workflows using GitHub CLI: - -```bash -# Check workflow runs -gh run list --workflow=ci.yml - -# Watch a specific run -gh run watch - -# Re-run failed jobs -gh run rerun --failed - -# View logs -gh run view --log - -# Check workflow status from PR -gh pr checks --watch - -# List recent workflow runs -gh run list --limit 10 - -# Download logs -gh run view --log > workflow.log -``` - ## Best Practices 1. **Pin action versions**: Use specific versions (`@v4`) or SHA hashes, not `@main` @@ -565,43 +32,3 @@ gh run view --log > workflow.log 6. **Caching**: Use `actions/cache` for dependencies to speed up workflows 7. **Concurrency control**: Use `concurrency` to cancel redundant workflow runs 8. **Timeout limits**: Set `timeout-minutes` to prevent hung jobs - -### Example Best Practice Implementation - -```yaml -jobs: - build: - runs-on: ubuntu-latest - timeout-minutes: 10 # Prevent jobs from hanging - concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true # Cancel old runs when new ones start - permissions: - contents: read # Minimal permissions - steps: - - uses: actions/checkout@v4 # Pinned version - - - name: Cache dependencies - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - - - run: npm ci - - run: npm test -``` - -## Resources - -- [GitHub Actions Documentation](https://docs.github.com/en/actions) -- [Workflow Syntax Reference](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) -- [Security Hardening Guide](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions) -- [act - Local Testing](https://github.com/nektos/act) -- [Awesome Actions](https://github.com/sdras/awesome-actions) -- [GitHub Actions Marketplace](https://github.com/marketplace?type=actions) - -## Related Skills - -- **github** - General GitHub operations, PR management, and API usage -- **github-pr-review** - Posting structured PR reviews -- **docker** - Working with Docker in GitHub Actions workflows From 6dd95045860c5d69e4dcee6a56ee5de928478361 Mon Sep 17 00:00:00 2001 From: openhands Date: Wed, 27 May 2026 22:31:16 +0000 Subject: [PATCH 7/8] refactor: address review feedback - condense SKILL.md, expand README.md - Fix grammar: 'should tested' -> 'should be tested' - Move detailed gh CLI commands, debugging workflow, and YAML debug-step examples from SKILL.md to README.md (progressive disclosure - SKILL.md is now 43 lines) - Keep core principles (cost awareness, monitor, read logs, print actual values, local-first, smallest reproduction) in SKILL.md as a concise decision guide - Expand README.md with full debugging loop, gh run/checks commands, log-reading patterns, act usage and caveats, visibility/debug-step example with runner.debug gating, cost-awareness practices, and pitfalls reference Co-authored-by: openhands --- skills/github-actions/README.md | 187 +++++++++++++++++++++++++++++--- skills/github-actions/SKILL.md | 53 ++------- 2 files changed, 180 insertions(+), 60 deletions(-) diff --git a/skills/github-actions/README.md b/skills/github-actions/README.md index e13d8908..895c892a 100644 --- a/skills/github-actions/README.md +++ b/skills/github-actions/README.md @@ -1,20 +1,18 @@ # GitHub Actions Skill -A comprehensive skill for creating, debugging, and testing GitHub Actions workflows and custom actions. +A skill focused on **effectiveness** when working with GitHub Actions — monitoring runs, reading logs, and developing actions with confidence rather than guessing. ## Overview -This skill provides guidance for working with GitHub Actions, including: +This skill provides guidance for: - Creating and structuring workflows -- Building custom actions (composite and reusable) -- Testing actions locally and in CI -- Debugging failed workflows -- Avoiding common pitfalls -- Best practices and security considerations +- Building custom composite and reusable actions +- Testing actions locally (before burning CI minutes) and in CI +- Debugging failed workflows from real evidence (logs), not assumptions +- Avoiding common pitfalls around permissions, secrets, and fork PRs ## When to Use This Skill -Use this skill when: - Creating new GitHub Actions workflows - Building custom composite or reusable actions - Debugging workflow failures @@ -22,13 +20,170 @@ Use this skill when: - Troubleshooting permission or secret issues - Testing actions before merging to main +## Cost Awareness + +Every workflow run consumes CI minutes (billed minutes on private repos, shared capacity on public ones). +Plan before you push: + +- Prefer one targeted commit that exercises the change over multiple speculative pushes +- Use `workflow_dispatch` with inputs to manually trigger only what you need +- Use `paths:` filters and `if:` conditions so jobs only run when relevant +- Run with `act` locally before opening a PR when feasible +- Cancel obsolete runs with `concurrency:` groups (don't pay for runs you've already invalidated) +- Use the smallest matrix that proves the change works; expand only if needed + +## Develop With Confidence: The Loop + +Don't change → push → hope. Use this loop: + +1. **Read** the existing workflow / action carefully. Note triggers, permissions, inputs, env, and secrets. +2. **Reproduce locally** with `act` when possible (see below). +3. **Add visibility** — debug steps that print non-secret inputs, refs, and intermediate state. +4. **Push a single focused commit**, then watch the run live. +5. **Read the full failed-job log** (not just the summary) before editing. +6. **Form a hypothesis from the log**, change the smallest thing that tests it, push, watch again. + +## Monitoring Runs With `gh` + +```bash +# Watch the most recent run from the current branch in real time +gh run watch + +# Watch a specific run +gh run watch + +# Auto-refresh PR checks until they finish (every 10s) +gh pr checks --watch --interval 10 + +# List recent runs for the repo / branch +gh run list --branch --limit 10 + +# Get the run ID for the latest run on a branch +gh run list --branch --limit 1 --json databaseId --jq '.[0].databaseId' +``` + +## Reading Logs (Don't Guess) + +```bash +# Full log for a run +gh run view --log + +# Just the failed steps (much shorter) +gh run view --log-failed + +# Log for a specific job (useful for matrix builds) +gh run view --log --job + +# List jobs for a run to find the job ID +gh run view --json jobs --jq '.jobs[] | {id, name, conclusion}' + +# Rerun only the failed jobs (avoid paying to rerun green ones) +gh run rerun --failed +``` + +When a step fails, look for: +- The exact command that exited non-zero (above the `##[error]` line) +- The shell — bash on Linux, `pwsh` on Windows runners — error messages differ +- Values printed by your debug step; compare against what the workflow *thought* it was passing in + +## Adding Visibility to Actions + +When creating a new action or hitting a tricky bug, add debug steps. Don't leave them in indefinitely — remove or guard them with `if: runner.debug == '1'` once the issue is understood. + +```yaml +steps: + # Print non-secret inputs and context at the start + - name: Debug - inputs and context + if: runner.debug == '1' || inputs.debug == 'true' + run: | + echo "Event: ${{ github.event_name }}" + echo "Ref: ${{ github.ref }}" + echo "SHA: ${{ github.sha }}" + echo "Actor: ${{ github.actor }}" + echo "PWD: $(pwd)" + echo "Input.my-param: ${{ inputs.my-param }}" + echo "Files:" + ls -la + + # ... your real steps ... + + # Verify outcome before the job ends + - name: Debug - verify outputs + if: always() && (runner.debug == '1' || inputs.debug == 'true') + run: | + echo "Generated files:" + ls -la dist/ || true + echo "Last exit code: $?" +``` + +To enable `runner.debug == '1'` for a single run, re-run the workflow with **"Enable debug logging"** checked, or set the repo secret `ACTIONS_RUNNER_DEBUG=true`. + +**Never** echo `${{ secrets.* }}` — GitHub masks them, but encoded forms (base64, hex, JSON-wrapped) can leak through. + +## Testing Locally With `act` + +`act` ([nektos/act](https://github.com/nektos/act)) runs workflows in Docker locally. Use it to iterate without burning CI minutes. + +```bash +# Run the default push event +act + +# Simulate a pull_request event +act pull_request + +# Run a specific job +act -j build + +# Pass secrets +act -s GITHUB_TOKEN="$GITHUB_TOKEN" + +# Use a larger image closer to GitHub's runner +act -P ubuntu-latest=catthehacker/ubuntu:full-latest +``` + +Caveats: `act` does not perfectly emulate GitHub's runners. Things that may differ: pre-installed tools, `GITHUB_TOKEN` permissions, OIDC, the `secrets.GITHUB_TOKEN` value, and macOS/Windows runners. Treat green-on-`act` as a strong signal, not a guarantee. + +## Testing Custom Actions Requires Merge to Main + +A repository-local custom action referenced as `uses: ./.github/actions/my-action` works from any branch, but: + +- A custom action published as `uses: owner/repo/action@ref` must have the action's files **on `ref`** to be resolvable +- `@main` or `@v1` must already exist when the workflow that consumes it runs +- This is why a brand-new action typically must land on `main` first, then be consumed from feature branches that reference `@main` (or a tag) + +If you need to iterate on an action and its consumer together, point `uses:` at a SHA on your branch, or develop the action via the local `./.github/actions/…` path until it's stable. + +## Common Pitfalls + +1. **Custom action not found from a PR** — the action's ref doesn't exist yet. Merge to `main` (or push a tag), then consume. +2. **`GITHUB_TOKEN` permissions** — defaults can be read-only. Set `permissions:` explicitly at the workflow or job level. +3. **`pull_request` vs `pull_request_target`** — `pull_request` runs in the fork's context (no secrets); `pull_request_target` runs with repo secrets against the base — **dangerous** if you check out PR code and execute it. Don't. +4. **Secrets in fork PRs** — even non-`*_target` workflows hide secrets from forks. Don't design workflows that require secrets to run on community PRs. +5. **Workflow file changes don't trigger themselves** — a new workflow added in a PR only runs after merge unless the trigger explicitly includes the PR event. +6. **Path filters are OR, not AND** — any matching path triggers; you can't require all paths. +7. **Matrix `fail-fast: true`** (default) cancels other matrix legs on first failure — turn off when you need full coverage. +8. **Artifacts** — files don't persist between jobs unless uploaded via `actions/upload-artifact` and downloaded in the consuming job. +9. **`env:` scope** — env at workflow, job, and step levels all exist. Step-level shadows job-level shadows workflow-level. Surprises follow if you forget. +10. **Pin versions** — use `@v4` (or better, a SHA) rather than `@main`. Floating refs break builds when upstream changes. + ## Best Practices -1. **Pin action versions**: Use specific versions (`@v4`) or SHA hashes, not `@main` -2. **Minimal permissions**: Explicitly set `permissions` to minimum required -3. **Debug steps**: Add debug output when creating new actions or troubleshooting tricky issues (not required for every workflow) -4. **Fail fast**: Use `fail-fast: false` in matrix builds only when needed -5. **Secrets handling**: Never print secrets; they're masked but can be exposed via encoding -6. **Caching**: Use `actions/cache` for dependencies to speed up workflows -7. **Concurrency control**: Use `concurrency` to cancel redundant workflow runs -8. **Timeout limits**: Set `timeout-minutes` to prevent hung jobs +1. **Pin action versions** — `@v4` or SHA, not `@main` +2. **Least privilege** — set `permissions:` to the minimum needed +3. **Debug steps when introducing or debugging** — remove or gate them with `runner.debug` afterward +4. **Cache dependencies** — `actions/cache` saves real minutes +5. **Concurrency** — cancel obsolete runs: + ```yaml + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + ``` +6. **Timeouts** — set `timeout-minutes:` on jobs that can hang +7. **Fail loudly** — `set -euo pipefail` in non-trivial bash steps +8. **Document non-obvious triggers/inputs** at the top of the workflow file + +## Related + +- [GitHub Actions documentation](https://docs.github.com/en/actions) +- [`act` — run actions locally](https://github.com/nektos/act) +- [`gh run` CLI reference](https://cli.github.com/manual/gh_run) diff --git a/skills/github-actions/SKILL.md b/skills/github-actions/SKILL.md index 47140742..c024ea37 100644 --- a/skills/github-actions/SKILL.md +++ b/skills/github-actions/SKILL.md @@ -14,7 +14,7 @@ triggers: **Custom Action Deployment:** - New custom actions MUST be merged to the main branch before they can be used -- After the initial merge, should tested from feature branches +- After the initial merge, they should be tested from feature branches **Debug Steps:** Add debug steps that print non-secret parameters when: @@ -23,51 +23,17 @@ Add debug steps that print non-secret parameters when: (Not required for every workflow - use when needed) -## Testing & Monitoring Strategy +## Effectiveness Principles -**Actions have costs** - Each workflow run consumes CI minutes. Plan efficiently: +Actions cost CI minutes. Be deliberate, not iterative: -1. **Use debug steps early** - don't guess, read actual values -2. **Monitor actively** - use `gh run watch ` or `gh pr checks --watch` -3. **Read logs immediately** - `gh run view --log` or view in GitHub UI -4. **Understand before changing** - examine what actually ran, not what you think ran +1. **Monitor, don't poll** - use `gh run watch` / `gh pr checks --watch` to follow runs live +2. **Read logs, don't guess** - fetch the failed job's log before changing code +3. **Print actual values** - debug steps reveal the real `inputs`/`github` context, not your assumptions +4. **Test locally first** - `act` runs workflows on your machine and avoids burning CI minutes +5. **Plan the smallest reproduction** - one job, minimal matrix, narrow trigger before scaling up -**Effective debugging workflow:** -```bash -# Watch workflow run in real-time -gh run watch - -# Or monitor PR checks with auto-refresh -gh pr checks --watch --interval 10 - -# When failed, read full logs immediately -gh run view --log - -# Examine specific job logs -gh run view --log --job= -``` - -**Add visibility to your actions:** -```yaml -steps: - # Print all non-secret inputs/context at start - - name: Debug - Action inputs - run: | - echo "Event: ${{ github.event_name }}" - echo "Ref: ${{ github.ref }}" - echo "Actor: ${{ github.actor }}" - echo "Working dir: $(pwd)" - echo "Custom input: ${{ inputs.my-param }}" - - # Your action logic here - - # Verify outcome before finishing - - name: Debug - Verify results - run: | - echo "Files created:" - ls -la - echo "Exit code: $?" -``` +See [README.md](README.md) for the full debugging workflow, `gh` commands, and YAML debug-step examples. ## Key Gotchas @@ -75,4 +41,3 @@ steps: 2. **Pin action versions** - Use `@v4` or SHA, not `@main` (prevents breaking changes) 3. **Explicit permissions** - Set `permissions:` block for GITHUB_TOKEN operations 4. **Artifacts for job-to-job data** - Files don't persist between jobs without `upload-artifact`/`download-artifact` - From 888acf2c4a54ecce09ad0a9d2e5104d0aebdbe72 Mon Sep 17 00:00:00 2001 From: openhands Date: Wed, 27 May 2026 22:57:18 +0000 Subject: [PATCH 8/8] refactor: address review feedback - tighten triggers, security wording, docs - SKILL.md: replace overly generic triggers (workflow, ci/cd) with GitHub Actions-specific ones to prevent false positives - SKILL.md: clarify pull_request_target risk (RCE if checking out fork code) - README.md: note Docker prerequisite for act - README.md: correct pitfall #5 - it's non-pull_request triggers (schedule/workflow_dispatch) that need to be on default branch, not pull_request workflows Co-authored-by: openhands --- skills/github-actions/README.md | 4 ++-- skills/github-actions/SKILL.md | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/skills/github-actions/README.md b/skills/github-actions/README.md index 895c892a..37907e83 100644 --- a/skills/github-actions/README.md +++ b/skills/github-actions/README.md @@ -122,7 +122,7 @@ To enable `runner.debug == '1'` for a single run, re-run the workflow with **"En ## Testing Locally With `act` -`act` ([nektos/act](https://github.com/nektos/act)) runs workflows in Docker locally. Use it to iterate without burning CI minutes. +`act` ([nektos/act](https://github.com/nektos/act)) runs workflows in Docker locally (Docker must be installed and running). Use it to iterate without burning CI minutes. ```bash # Run the default push event @@ -159,7 +159,7 @@ If you need to iterate on an action and its consumer together, point `uses:` at 2. **`GITHUB_TOKEN` permissions** — defaults can be read-only. Set `permissions:` explicitly at the workflow or job level. 3. **`pull_request` vs `pull_request_target`** — `pull_request` runs in the fork's context (no secrets); `pull_request_target` runs with repo secrets against the base — **dangerous** if you check out PR code and execute it. Don't. 4. **Secrets in fork PRs** — even non-`*_target` workflows hide secrets from forks. Don't design workflows that require secrets to run on community PRs. -5. **Workflow file changes don't trigger themselves** — a new workflow added in a PR only runs after merge unless the trigger explicitly includes the PR event. +5. **New trigger types don't take effect until merged** — a `schedule:` or `workflow_dispatch:` trigger added in a PR only fires after merge; `pull_request`-triggered workflows do run on the PR that introduces them. 6. **Path filters are OR, not AND** — any matching path triggers; you can't require all paths. 7. **Matrix `fail-fast: true`** (default) cancels other matrix legs on first failure — turn off when you need full coverage. 8. **Artifacts** — files don't persist between jobs unless uploaded via `actions/upload-artifact` and downloaded in the consuming job. diff --git a/skills/github-actions/SKILL.md b/skills/github-actions/SKILL.md index c024ea37..409a8a0e 100644 --- a/skills/github-actions/SKILL.md +++ b/skills/github-actions/SKILL.md @@ -3,9 +3,10 @@ name: github-actions description: Create, debug, and test GitHub Actions workflows and custom actions. Use when building CI/CD pipelines, automating workflows, or troubleshooting GitHub Actions. triggers: - github actions -- workflow -- ci/cd - github workflow +- actions workflow +- gh actions +- .github/workflows --- # GitHub Actions Guide @@ -37,7 +38,7 @@ See [README.md](README.md) for the full debugging workflow, `gh` commands, and Y ## Key Gotchas -1. **Secrets unavailable in fork PRs** - Use `pull_request_target` with caution or don't rely on secrets +1. **Secrets unavailable in fork PRs** - `pull_request` has no secrets for forks; `pull_request_target` does but **never check out or execute fork PR code inside it** (RCE with write permissions) 2. **Pin action versions** - Use `@v4` or SHA, not `@main` (prevents breaking changes) 3. **Explicit permissions** - Set `permissions:` block for GITHUB_TOKEN operations 4. **Artifacts for job-to-job data** - Files don't persist between jobs without `upload-artifact`/`download-artifact`