Loading...
Loading...
Create and configure GitHub Actions. Use when building custom actions, setting up runners, implementing security practices, or publishing to the marketplace.
npx skill4agent add vinnie357/claude-skills github-actionsmy-action/
├── action.yml # Metadata and interface
├── index.js # Entry point
├── package.json # Dependencies
└── node_modules/ # Bundled dependencies@actions/core@actions/githubname: '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'my-action/
├── action.yml
├── Dockerfile
├── entrypoint.sh
└── src/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"]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: bashname: 'Action Name' # Marketplace display name
description: 'What it does' # Clear, concise purpose
runs: # Execution configuration
using: 'node20' # or 'docker' or 'composite'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'const core = require('@actions/core');
const token = core.getInput('token', { required: true });
const config = core.getInput('config') || 'default.yml';TOKEN="${{ inputs.token }}"
CONFIG="${{ inputs.config }}"core.setOutput('result', 'success');
core.setOutput('artifact-url', artifactUrl);echo "result=success" >> $GITHUB_OUTPUT
echo "artifact-url=$ARTIFACT_URL" >> $GITHUB_OUTPUTconst 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');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'
});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(); }
}
});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);permissions:
contents: read # Read repository
pull-requests: write # Comment on PRs
issues: write # Create issues// 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# 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 distgit tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0# 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- uses: owner/action@v1 # Tracks latest v1.x.xact# Test action in current directory
act -j test
# Test with specific event
act push
# Test with secrets
act -s GITHUB_TOKEN=ghp_xxx# 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: bashconst 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}`);
}
}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);
}# Add required permissions to workflow
permissions:
contents: write
pull-requests: writedocker build -t test . && docker run test