원클릭으로
crete-reusable-action
Create a new reusable composite GitHub Action with well-defined inputs/outputs that can be used by customer workflows.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Create a new reusable composite GitHub Action with well-defined inputs/outputs that can be used by customer workflows.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | crete-reusable-action |
| description | Create a new reusable composite GitHub Action with well-defined inputs/outputs that can be used by customer workflows. |
Use this skill when you need to:
Use when:
Examples in this repo:
actions/build/env-pairs-to-dot-env/action.yaml - Converts env pairs to .env fileactions/build/dotenv-to-ghaction-env/action.yaml - Loads .env into GitHub Actions environmentactions/github/check-runs-create/action.yaml - Creates GitHub check run via curlproducts/lookinglass/manage-records/to-github-actions-matrix/action.yaml - Processes YAML to matrixUse when:
Examples in this repo:
actions/github/ghas-dependabot-metadata/action.yaml - Fetches Dependabot metadata and creates PR commentsactions/github/lint-gha-sha-version/action.yaml - Downloads and runs gha-fix CLI with complex setupactions/build/openssf-dependency-metadata/action.yaml - Fetches deps.dev API and formats resultsactions/messaging/slack-notification/action.yaml - Email-to-Slack mention conversion with API callsIMPORTANT: JavaScript actions MUST use actions/github-script@vX with inline pure JavaScript.
fs, path, os, child_process, crypto, etc.@actions/core, @actions/github, github context, fetch (Node 20+)actions/
├── {category}/ # build, docker, github, messaging, network
│ └── {action-name}/ # descriptive-kebab-case name
│ └── action.yaml # MUST be action.yaml (not action.yml)
Categories:
build/ - Build utilities, configuration, environment managementdocker/ - Docker-specific operations (scanning, SBOM, registry)github/ - GitHub API operations, workflow management, GHASmessaging/ - Notifications (Slack, email, etc.)network/ - Network utilities, runner operationsproducts/
├── {product}/ # lift, lookinglass
│ └── {domain}/ # manage-env, manage-repo, manage-issue, etc.
│ └── {action}/ # specific action name
│ └── action.yaml
Products:
lift/ - Environment management productlookinglass/ - Repository management and issue-ops productname: {Action Name}
description: {Clear description of what this action does}
author: {team-name or vionix}
branding:
icon: anchor
color: blue
inputs:
input-name:
description: "{Clear description of the input}"
required: true
default: "" # Only if optional
outputs:
output-name:
description: "{Clear description of the output}"
value: ${{ steps.step-id.outputs.output-name }}
runs:
using: composite
steps:
- name: {Descriptive step name}
id: step-id
shell: bash
env:
INPUT_VAR: ${{ inputs.input-name }}
run: |
# Shell script implementation
echo "Processing ${INPUT_VAR}"
# Set output
echo "output-name=value" >> $GITHUB_OUTPUT
# Add to job summary
echo "## Summary" >> $GITHUB_STEP_SUMMARY
echo "Processed successfully" >> $GITHUB_STEP_SUMMARY
name: {Action Name}
description: {Clear description of what this action does}
author: {team-name or vionix}
branding:
icon: anchor
color: blue
inputs:
github-token:
description: "GitHub token for API access"
required: true
input-name:
description: "{Clear description}"
required: true
outputs:
output-name:
description: "{Clear description}"
value: ${{ steps.process.outputs.output-name }}
runs:
using: composite
steps:
- name: {Descriptive step name}
id: process
uses: actions/github-script@v8
env:
INPUT_VAR: ${{ inputs.input-name }}
with:
github-token: ${{ inputs.github-token }}
script: |
const core = require('@actions/core');
const github = require('@actions/github');
const fs = require('fs');
const path = require('path');
// Get inputs from environment
const inputVar = process.env.INPUT_VAR || '';
// Process data
const result = processData(inputVar);
// Set outputs
core.setOutput('output-name', result);
// Add to job summary
await core.summary
.addHeading('Summary', 2)
.addRaw(`Processed: ${result}`)
.write();
// Helper functions
function processData(input) {
// Implementation
return input.toUpperCase();
}
name: {Composite Action Name}
description: {Description of the cohesive problem this solves}
inputs:
input-1:
description: "First input"
required: true
input-2:
description: "Second input"
required: false
default: "default-value"
outputs:
final-output:
description: "The final result"
value: ${{ steps.combine.outputs.result }}
runs:
using: composite
steps:
# Step 1: Prepare data
- name: Prepare data
id: prepare
shell: bash
run: |
echo "Preparing ${{ inputs.input-1 }}"
echo "prepared=true" >> $GITHUB_OUTPUT
# Step 2: Use existing action
- name: Process with existing action
id: process
uses: Viasat/vionix/actions/category/action@main
with:
input: ${{ inputs.input-1 }}
# Step 3: Combine results with JavaScript
- name: Combine results
id: combine
uses: actions/github-script@v8
env:
PREPARED: ${{ steps.prepare.outputs.prepared }}
PROCESSED: ${{ steps.process.outputs.result }}
with:
script: |
const prepared = process.env.PREPARED === 'true';
const processed = process.env.PROCESSED || '';
const result = prepared ? `Combined: ${processed}` : 'Failed';
core.setOutput('result', result);
required: true for mandatory inputsShell:
if [ ! -f "required-file.txt" ]; then
echo "ERROR: required-file.txt does not exist!"
exit 1
fi
JavaScript:
try {
const result = await riskyOperation();
core.setOutput('result', result);
} catch (error) {
core.setFailed(`Operation failed: ${error.message}`);
return;
}
core.setSecret() to mask sensitive values in JavaScriptgithub-token input instead of hardcoding secrets.GITHUB_TOKENExample:
const token = process.env.GITHUB_TOKEN || '';
if (token) core.setSecret(token);
Always add meaningful summaries using $GITHUB_STEP_SUMMARY:
Shell:
echo "## Action Results" >> $GITHUB_STEP_SUMMARY
echo "- Status: Success ✅" >> $GITHUB_STEP_SUMMARY
echo "- Files processed: ${COUNT}" >> $GITHUB_STEP_SUMMARY
JavaScript:
await core.summary
.addHeading('Action Results', 2)
.addRaw('- Status: Success ✅\n')
.addRaw(`- Files processed: ${count}\n`)
.write();
Composite actions can call other actions:
- name: Use existing action
uses: Viasat/vionix/actions/build/dotenv-to-ghaction-env@main
with:
dot-file-path: .env
act or in a test workflow.github/workflows/test-*.yamlsteps:
- name: Process files
shell: bash
run: |
for file in *.yaml; do
echo "Processing $file"
yq eval '.field' "$file"
done
async function fetchWithRetry(url, options, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, options);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
if (i === retries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
const octokit = github.getOctokit(process.env.GITHUB_TOKEN);
// Create issue comment
await octokit.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: 'Comment text'
});
// List files in PR
const { data: files } = await octokit.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});
# Shell - Use EOF delimiters
echo 'multiline-output<<EOF' >> $GITHUB_OUTPUT
echo "Line 1" >> $GITHUB_OUTPUT
echo "Line 2" >> $GITHUB_OUTPUT
echo 'EOF' >> $GITHUB_OUTPUT
// JavaScript
const multilineValue = `
Line 1
Line 2
Line 3
`.trim();
core.setOutput('multiline-output', multilineValue);
steps:
- name: Check condition
id: check
shell: bash
run: |
if [ "${{ inputs.enable-feature }}" == "true" ]; then
echo "enabled=true" >> $GITHUB_OUTPUT
else
echo "enabled=false" >> $GITHUB_OUTPUT
fi
- name: Run if enabled
if: ${{ steps.check.outputs.enabled == 'true' }}
shell: bash
run: echo "Feature is enabled"
Below are inline code patterns found in existing workflows that should be extracted into reusable actions:
Found in: Multiple workflows (docker-compose-devsecops-workflow.yaml, etc.)
Pattern: Extracting git SHA, branch name, committer info
Proposed action: actions/github/extract-git-metadata/action.yaml
# Extract from workflows like:
# gitShortSha: $(git rev-parse --short HEAD)
# committerName: $(git log -1 --pretty=format:'%an')
# committerEmail: $(git log -1 --pretty=format:'%ae')
# Should output: sha, shortSha, branch, committer.name, committer.email, timestamp
Found in: docker-compose-devsecops-workflow.yaml (lines 192-200)
Pattern: Generating Docker image tags from branch names and SHAs
Proposed action: actions/docker/generate-image-tags/action.yaml
# Generate standardized tags:
# - defaultDockerImageVersion
# - defaultDockerImageBranchTag
# - defaultDockerImageBranchShaTag
# - defaultDockerImageBranchTagForVersion
Found in: Multiple workflows (279 shell runs for notifications)
Pattern: Building Slack payloads with job context
Proposed action: actions/messaging/build-slack-payload/action.yaml
# Already partially done in slack-notification/action.yaml
# But many workflows still build payloads inline
# Should standardize: success/failure payloads, link formatting, emoji status
Found in: Multiple workflows
Pattern: Generating job URLs for linking in notifications
Proposed action: actions/github/generate-job-url/action.yaml
# Extract from:
# githubActionJobUrl: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
# Should handle: job URLs, step URLs, PR URLs, commit URLs
Found in: docker-compose-devsecops-workflow.yaml and others
Pattern: Validating YAML/JSON files with exclusion patterns
Proposed action: actions/build/validate-config-files/action.yaml
# Inputs: file-pattern, exclude-regex, allow-multiple-documents
# Should validate syntax, report errors, support both YAML and JSON
Found in: Multiple workflows using github-script inline
Pattern: Fetching PR number, title, author, labels
Proposed action: actions/github/fetch-pr-context/action.yaml
# Get PR metadata in any event (push, pull_request, workflow_dispatch)
# Outputs: pr-number, pr-title, pr-author, pr-labels, is-pr
Found in: Multiple workflows with docker login commands
Pattern: Authenticating to Artifactory registry
Proposed action: actions/docker/artifactory-login/action.yaml
# Inputs: username, password, registry-url
# Handle: docker login, credential masking, logout on failure
Found in: docker-compose workflows
Pattern: Generating ISO timestamps for build metadata
Proposed action: actions/build/generate-timestamp/action.yaml
# Generate: ISO8601, Unix epoch, formatted timestamps
# For: build metadata, cache keys, artifact naming
Found in: terraform-devsecops-workflow.yaml, security scanning workflows
Pattern: Uploading SARIF files to GHAS with error handling
Proposed action: actions/github/upload-sarif-results/action.yaml
# Handle: SARIF validation, upload to GHAS, retry logic, error reporting
Found in: Workflows with dynamic matrix generation
Pattern: Building GitHub Actions matrix from files or API responses
Proposed action: actions/github/build-matrix-strategy/action.yaml
# Partially exists in: products/lookinglass/manage-records/to-github-actions-matrix
# Should generalize: support JSON/YAML input, filtering, transformation
Found in: Multiple workflows with env file handling
Pattern: Loading environment variables from various sources
Proposed action: actions/build/inject-environment-vars/action.yaml
# Combine: env-pairs-to-dot-env + dotenv-to-ghaction-env
# Add: support for JSON, YAML, env files, base64 encoded
Found in: PR workflows checking changed files
Pattern: Getting changed files list, filtering by pattern
Proposed action: actions/github/analyze-git-diff/action.yaml
# Outputs: changed-files (list), has-changes (bool), file-count
# Support: glob patterns, exclude patterns, base branch comparison
Found in: Docker build workflows with sonarqube scanning
Pattern: Submitting scan results to SonarQube
Proposed action: actions/build/sonarqube-reporter/action.yaml
Found in: Multiple workflows with submodule handling
Pattern: Conditional checkout with submodule support
Proposed action: actions/github/checkout-with-options/action.yaml
Found in: Workflows using actions/cache
Pattern: Generating cache keys from file hashes
Proposed action: actions/build/generate-cache-key/action.yaml
actions/{category}/{action-name}/products/{product}/{domain}/{action}/mkdir -p actions/github/my-new-action
cd actions/github/my-new-action
Create a test workflow:
name: Test My Action
on: workflow_dispatch
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Test action
uses: ./actions/github/my-new-action
with:
input-name: test-value
- name: Verify output
run: echo "Output was ${{ steps.test.outputs.output-name }}"
- name: Convert env pairs to .env
uses: Viasat/vionix/actions/build/env-pairs-to-dot-env@v1.2.3
with:
dot-file-content: |
KEY1=value1
KEY2=value2
dot-file-artifact-name: build-env
dot-file-path: .env.build
- name: Get Dependabot metadata
id: metadata
uses: Viasat/vionix/actions/github/ghas-dependabot-metadata@v2.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
github-enterprise: "true"
- name: Use metadata output
run: echo "Dependency: ${{ steps.metadata.outputs.dependabotMetadata }}"
- name: Authenticate to GitHub
id: auth
uses: Viasat/vionix/products/lookinglass/manage-repo/authenticate@main
with:
authentication: app
application-id: ${{ secrets.APP_ID }}
application-private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Use authenticated token
run: |
echo "Token: ${{ steps.auth.outputs.token }}"
Add debug output:
echo "::debug::Variable value is ${VAR}"
core.debug(`Variable value is ${var}`);
# Shell - Use jq
echo '{"key":"value"}' | jq -r '.key'
# Create JSON array
jq -n --arg val "$VALUE" '{"key": $val}'
// JavaScript - Native support
const obj = JSON.parse(jsonString);
const result = JSON.stringify({ key: 'value' });
const fs = require('fs');
const path = require('path');
// Read file
const content = fs.readFileSync('file.txt', 'utf8');
// Write file
fs.writeFileSync('output.txt', content, 'utf8');
// Check if file exists
if (fs.existsSync('file.txt')) {
// File exists
}
// Create directory
fs.mkdirSync('new-dir', { recursive: true });
// Get workspace path
const workspace = process.env.GITHUB_WORKSPACE || process.cwd();
// Get runner temp
const temp = process.env.RUNNER_TEMP || '/tmp';
// Get GitHub context
const eventName = process.env.GITHUB_EVENT_NAME;
// Always use async/await in github-script
const result = await asyncOperation();
// Parallel operations
const [result1, result2] = await Promise.all([
operation1(),
operation2()
]);
Remember: Actions should solve ONE cohesive problem. If your action does too many unrelated things, consider splitting it into multiple actions that can be composed together.
Map internal corporate author identities (name + email) to public github.com identities using MCP-driven user lookup, then rewrite git history with git-filter-repo + .mailmap. Specific to CNCF OSS migration workflows.
Inject and validate the legal and governance documents required for a CNCF-compliant open-source project: Apache 2.0, DCO, GOVERNANCE, SECURITY, CODE_OF_CONDUCT, and README hygiene. Specific to CNCF OSS migration.
Technically migrate a clean repository from GitHub Enterprise Server (GHES) to a public github.com org using squash-to-milestones or mirror-push, then configure branch protection and least-privilege RBAC. Specific to CNCF OSS migration.
Integrate CNCF CLOMonitor and OpenSSF Scorecard into CI/CD to continuously validate open-source project health after a GHES-to-github.com migration. Specific to CNCF OSS migration post-validation workflows.
Scan and strip hardcoded secrets, internal credentials, corporate hostnames, and proprietary naming from a GitHub Enterprise repo before it goes public. Specific to the Vionix CNCF migration workflow — do not use for general code review.
File a Vionix LookinGlass mirror request for a github.com GitHub Action by filling out the IssueOps form at https://<git-host>/github/vionix-lookinglass/issues/new?template=mirrorrepo.yaml. Use this skill whenever the user asks to mirror a github.com repo/action into <git-host>, to "create a mirror request", "onboard a github action", or mentions vionix-lookinglass mirror issues — even if they only provide the upstream URL. It maps the user's intent to every form field, submits the issue with the gh CLI, and explains the follow-up IssueOps commands (@vionix validate, @vionix lgtm) and the GHAS exposed-secrets resume flow.