Claude-skill-registry github-actions
Create and configure GitHub Actions. Use when building custom actions, setting up runners, implementing security practices, or publishing to the marketplace.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/actions" ~/.claude/skills/majiayu000-claude-skill-registry-github-actions && rm -rf "$T"
skills/data/actions/SKILL.md- global npm install
- eval/exec/Function constructor
- makes HTTP requests (curl)
- git push --force
GitHub Actions
Activate when creating, modifying, troubleshooting, or optimizing GitHub Actions components. This skill covers action development, marketplace integration, and best practices.
When to Use This Skill
Activate when:
- Creating custom GitHub Actions (JavaScript, Docker, or composite)
- Publishing actions to GitHub Marketplace
- Configuring action metadata and inputs/outputs
- Implementing action security and permissions
- Troubleshooting action execution
- Selecting or evaluating marketplace actions
- Optimizing action performance and reliability
Action Types
JavaScript Actions
Execute directly on runners with fast startup and cross-platform compatibility.
Structure:
my-action/ ├── action.yml # Metadata and interface ├── index.js # Entry point ├── package.json # Dependencies └── node_modules/ # Bundled dependencies
Key Requirements:
- Use
for inputs/outputs@actions/core - Use
for GitHub API access@actions/github - Bundle all dependencies (use @vercel/ncc)
- Support Node.js LTS versions
Example action.yml:
name: 'My JavaScript Action' description: 'Performs custom task' inputs: token: description: 'GitHub token' required: true config: description: 'Configuration file path' required: false default: 'config.yml' outputs: result: description: 'Action result' runs: using: 'node20' main: 'dist/index.js'
Docker Container Actions
Provide consistent execution environment with all dependencies packaged.
Structure:
my-action/ ├── action.yml ├── Dockerfile ├── entrypoint.sh └── src/
Key Requirements:
- Use lightweight base images (Alpine when possible)
- Set proper file permissions
- Handle signals gracefully
- Output to STDOUT/STDERR correctly
Example Dockerfile:
FROM alpine:3.18 RUN apk add --no-cache bash curl jq COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]
Composite Actions
Combine multiple steps and actions into reusable units.
Structure:
name: 'Setup Environment' description: 'Configure development environment' inputs: node-version: description: 'Node.js version' required: false default: '20' runs: using: 'composite' steps: - uses: actions/setup-node@v4 with: node-version: ${{ inputs.node-version }} - run: npm ci shell: bash - run: npm run build shell: bash
Action Metadata (action.yml)
Required Fields
name: 'Action Name' # Marketplace display name description: 'What it does' # Clear, concise purpose runs: # Execution configuration using: 'node20' # or 'docker' or 'composite'
Optional Fields
author: 'Your Name' branding: # Marketplace icon/color icon: 'activity' color: 'blue' inputs: # Define all inputs input-name: description: 'Purpose' required: true default: 'value' outputs: # Define all outputs output-name: description: 'What it contains'
Inputs and Outputs
Reading Inputs
JavaScript:
const core = require('@actions/core'); const token = core.getInput('token', { required: true }); const config = core.getInput('config') || 'default.yml';
Shell:
TOKEN="${{ inputs.token }}" CONFIG="${{ inputs.config }}"
Setting Outputs
JavaScript:
core.setOutput('result', 'success'); core.setOutput('artifact-url', artifactUrl);
Shell:
echo "result=success" >> $GITHUB_OUTPUT echo "artifact-url=$ARTIFACT_URL" >> $GITHUB_OUTPUT
GitHub Actions Toolkit
Essential npm packages for JavaScript actions:
@actions/core
const core = require('@actions/core'); // Inputs/Outputs const input = core.getInput('name'); core.setOutput('name', value); // Logging core.info('Information message'); core.warning('Warning message'); core.error('Error message'); core.debug('Debug message'); // Grouping core.startGroup('Group name'); // ... operations core.endGroup(); // Failure core.setFailed('Action failed: reason'); // Secrets core.setSecret('sensitive-value'); // Masks in logs // Environment core.exportVariable('VAR_NAME', 'value');
@actions/github
const github = require('@actions/github'); // Context const context = github.context; console.log(context.repo); // { owner, repo } console.log(context.sha); // Commit SHA console.log(context.ref); // Branch/tag ref console.log(context.actor); // Triggering user console.log(context.payload); // Webhook payload // Octokit client const token = core.getInput('token'); const octokit = github.getOctokit(token); // API operations const { data: issues } = await octokit.rest.issues.listForRepo({ owner: context.repo.owner, repo: context.repo.repo, state: 'open' });
@actions/exec
const exec = require('@actions/exec'); // Execute commands await exec.exec('npm', ['install']); // Capture output let output = ''; await exec.exec('git', ['log', '--oneline'], { listeners: { stdout: (data) => { output += data.toString(); } } });
Security Best Practices
Input Validation
Always validate and sanitize inputs:
const core = require('@actions/core'); function validateInput(input) { // Check for command injection if (/[;&|`$()]/.test(input)) { throw new Error('Invalid characters in input'); } return input; } const userInput = core.getInput('user-input'); const safeInput = validateInput(userInput);
Token Permissions
Request minimal required permissions:
permissions: contents: read # Read repository pull-requests: write # Comment on PRs issues: write # Create issues
Secret Handling
// Mask secrets in logs core.setSecret(sensitiveValue); // Never log tokens core.debug(`Token: ${token}`); // ❌ WRONG core.debug('Token received'); // ✅ CORRECT // Secure token usage const octokit = github.getOctokit(token); // Token automatically included in requests
Dependency Security
# Audit dependencies npm audit # Use specific versions npm install @actions/core@1.10.0 # Bundle dependencies npm install -g @vercel/ncc ncc build index.js -o dist
Marketplace Publishing
Prerequisites
- Public repository
- action.yml in repository root
- README.md with usage examples
- LICENSE file
- Repository topics (optional)
Publishing Process
- Create release with semantic version tag:
git tag -a v1.0.0 -m "Release v1.0.0" git push origin v1.0.0
- Create GitHub Release from tag
- Check "Publish this Action to GitHub Marketplace"
- Select primary category
- Verify branding icon/color
Version Management
Use semantic versioning with major version tags:
# Release v1.2.3 git tag -a v1.2.3 -m "Release v1.2.3" git tag -fa v1 -m "Update v1 to v1.2.3" git push origin v1.2.3 v1 --force
Users reference by major version:
- uses: owner/action@v1 # Tracks latest v1.x.x
Testing Actions Locally
Use
act for local testing (see act skill):
# Test action in current directory act -j test # Test with specific event act push # Test with secrets act -s GITHUB_TOKEN=ghp_xxx
Common Patterns
Matrix Testing Action
# action.yml name: 'Matrix Test Runner' description: 'Run tests across multiple configurations' inputs: matrix-config: description: 'JSON matrix configuration' required: true runs: using: 'composite' steps: - run: | echo "Testing with config: ${{ inputs.matrix-config }}" # Parse and execute tests shell: bash
Cache Management Action
const core = require('@actions/core'); const cache = require('@actions/cache'); async function run() { const paths = [ 'node_modules', '.npm' ]; const key = `deps-${process.platform}-${hashFiles('package-lock.json')}`; // Restore cache const cacheKey = await cache.restoreCache(paths, key); if (!cacheKey) { core.info('Cache miss, installing dependencies'); await exec.exec('npm', ['ci']); await cache.saveCache(paths, key); } else { core.info(`Cache hit: ${cacheKey}`); } }
Artifact Upload Action
const artifact = require('@actions/artifact'); async function uploadArtifact() { const artifactClient = artifact.create(); const files = [ 'dist/bundle.js', 'dist/styles.css' ]; const rootDirectory = 'dist'; const options = { continueOnError: false }; const uploadResponse = await artifactClient.uploadArtifact( 'build-artifacts', files, rootDirectory, options ); core.setOutput('artifact-id', uploadResponse.artifactId); }
Troubleshooting
Action Not Found
- Verify repository is public or accessible
- Check action.yml exists in repository root
- Confirm version tag exists
Permission Denied
# Add required permissions to workflow permissions: contents: write pull-requests: write
Node Modules Missing
- Bundle dependencies with ncc
- Check dist/ folder is committed
- Verify node_modules excluded from .gitignore for dist/
Docker Action Fails
- Check Dockerfile syntax
- Verify entrypoint has execute permissions
- Test container locally:
docker build -t test . && docker run test
Anti-Fabrication Requirements
- Execute Read or Glob tools to verify action files exist before claiming structure
- Use Bash to test commands before documenting syntax
- Validate action.yml schema against actual files using tool analysis
- Execute actual API calls with @actions/github before documenting responses
- Test permission configurations in real workflows before recommending settings
- Never claim action capabilities without reading actual implementation code
- Report actual npm audit results when discussing security, not fabricated vulnerability counts