From 6cad19141db0f2c91e8670ba7308834c83a7c784 Mon Sep 17 00:00:00 2001 From: openhands Date: Wed, 18 Feb 2026 21:03:10 +0000 Subject: [PATCH 1/6] 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 7118f6d..c6e8798 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 0000000..9f20a5a --- /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 0000000..b9fb8fd --- /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/6] 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 9f20a5a..55c715c 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 b9fb8fd..22fad58 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/6] 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 55c715c..8cb1fb3 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 22fad58..60f3621 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/6] 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 60f3621..9b11f4d 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/6] 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 9b11f4d..4714074 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/6] 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 8cb1fb3..e13d890 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