github-actions by bobmatnyc/claude-mpm-skills
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill github-actionsGitHub Actions 是 GitHub 的原生 CI/CD 平台,用于自动化软件工作流。通过 YAML 文件定义工作流,利用事件驱动的自动化直接从您的仓库构建、测试和部署代码。
创建 .github/workflows/test.yml:
name: Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
位于 .github/workflows/ 目录下的 YAML 文件,用于定义自动化流水线。
结构:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
名称:工作流标识符
触发器:启动工作流的事件
作业:要执行的一个或多个作业
步骤:每个作业内的命令/操作
name: CI Pipeline on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: echo "Building project"
独立的执行单元,默认情况下并行运行。
jobs:
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint
test:
runs-on: ubuntu-latest
needs: lint # 等待 lint 完成
steps:
- run: npm test
deploy:
runs-on: ubuntu-latest
needs: [lint, test] # 等待两者都完成
steps:
- run: ./deploy.sh
作业内的顺序命令或操作。
steps:
# 使用预构建的操作
- uses: actions/checkout@v4
# 运行 shell 命令
- run: npm install
# 带环境的命名步骤
- name: Run tests
run: npm test
env:
NODE_ENV: test
可重用的代码单元(来自市场或自定义)。
# 官方操作
- uses: actions/checkout@v4
# 第三方操作
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: user/app:latest
# 本地操作
- uses: ./.github/actions/custom-action
on:
push:
branches:
- main
- 'releases/**' # 通配符模式
tags:
- 'v*' # 所有版本标签
paths:
- 'src/**'
- '!src/docs/**' # 排除文档
on:
pull_request:
types: [opened, synchronize, reopened]
branches: [main, develop]
paths-ignore:
- '**.md'
- 'docs/**'
on:
schedule:
# 每天 UTC 时间 2:30 AM
- cron: '30 2 * * *'
# 每周一 UTC 时间 9:00 AM
- cron: '0 9 * * 1'
on:
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
type: choice
options:
- staging
- production
version:
description: '要部署的版本'
required: false
default: 'latest'
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 0' # 每周
workflow_dispatch: # 手动
env:
NODE_ENV: production
API_URL: https://api.example.com
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo $NODE_ENV
jobs:
test:
runs-on: ubuntu-latest
env:
TEST_DATABASE: test_db
steps:
- run: pytest
steps:
- name: Build
run: npm run build
env:
BUILD_TARGET: production
将敏感数据存储在仓库设置中。
steps:
- name: Deploy
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
最佳实践:
仓库和工作流信息。
steps:
- name: Print context
run: |
echo "Repository: ${{ github.repository }}"
echo "Ref: ${{ github.ref }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
echo "Event: ${{ github.event_name }}"
echo "Branch: ${{ github.ref_name }}"
访问环境变量。
env:
BUILD_ID: 12345
steps:
- run: echo "Build ${{ env.BUILD_ID }}"
访问仓库密钥。
- run: echo "Token exists"
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
访问矩阵值。
strategy:
matrix:
node: [18, 20, 22]
steps:
- run: echo "Testing Node ${{ matrix.node }}"
访问依赖作业的输出。
jobs:
build:
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- id: get_version
run: echo "version=1.2.3" >> $GITHUB_OUTPUT
deploy:
needs: build
steps:
- run: echo "Deploying ${{ needs.build.outputs.version }}"
jobs:
ubuntu:
runs-on: ubuntu-latest # ubuntu-22.04
macos:
runs-on: macos-latest # macOS 14
windows:
runs-on: windows-latest # Windows 2022
specific:
runs-on: ubuntu-20.04 # 特定版本
可用运行器:
ubuntu-latest, ubuntu-22.04, ubuntu-20.04macos-latest, macos-14, macos-13windows-latest, windows-2022, windows-2019runs-on: self-hosted
# 带标签
runs-on: [self-hosted, linux, x64, gpu]
设置:
跨多个版本进行测试。
strategy:
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
strategy:
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
include:
# 添加特定组合
- node: 22
os: macos-latest
experimental: true
exclude:
# 移除特定组合
- node: 18
os: windows-latest
strategy:
fail-fast: false # 如果一个失败,继续其他作业
matrix:
node: [18, 20, 22]
strategy:
max-parallel: 2 # 仅同时运行 2 个作业
matrix:
node: [18, 20, 22]
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 用于变更日志的完整历史记录
submodules: true # 包含子模块
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # 或 'yarn', 'pnpm'
registry-url: 'https://registry.npmjs.org'
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'maven'
- uses: actions/setup-go@v5
with:
go-version: '1.21'
cache: true
- uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
steps:
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: ./deploy.sh
- name: Deploy to staging
if: github.ref == 'refs/heads/develop'
run: ./deploy-staging.sh
- name: Only on PR
if: github.event_name == 'pull_request'
run: echo "This is a PR"
- name: On success
if: success()
run: echo "Previous steps succeeded"
- name: On failure
if: failure()
run: echo "A step failed"
- name: Always run
if: always()
run: echo "Cleanup tasks"
jobs:
deploy:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
name: Node.js CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run type-check
- run: npm test
env:
CI: true
- run: npm run build
- uses: codecov/codecov-action@v4
if: matrix.node-version == 20
with:
token: ${{ secrets.CODECOV_TOKEN }}
name: Python CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- run: pip install -r requirements.txt
- run: pip install pytest pytest-cov mypy ruff
- run: ruff check .
- run: mypy .
- run: pytest --cov=. --cov-report=xml
- uses: codecov/codecov-action@v4
if: matrix.python-version == '3.11'
name: Docker Build
on:
push:
branches: [main]
tags: ['v*']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: user/app
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
name: Next.js CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run build
- run: npm test
deploy-preview:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
deploy-production:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
name: Deploy to Netlify
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run build
- uses: netlify/actions/cli@master
with:
args: deploy --prod --dir=dist
env:
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
name: Deploy to AWS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run build
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- run: aws s3 sync dist/ s3://${{ secrets.S3_BUCKET }} --delete
- run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \
--paths "/*"
name: Publish Docker Image
on:
release:
types: [published]
jobs:
push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}
name: Test Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test -- --coverage
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/coverage-final.json
fail_ci_if_error: true
name: Integration Tests
on: [push, pull_request]
jobs:
integration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run test:integration
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
REDIS_URL: redis://localhost:6379
name: E2E Tests
on: [push, pull_request]
jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx playwright install --with-deps
- run: npm run build
- run: npm run test:e2e
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 用于变更日志的完整历史记录
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
name: Create Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: changelog
run: |
# 从提交生成变更日志
CHANGELOG=$(git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:"- %s (%h)" --no-merges)
echo "changelog<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
release_name: Release ${{ github.ref_name }}
body: |
## Changes
${{ steps.changelog.outputs.changelog }}
draft: false
prerelease: false
name: Publish to npm
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm test
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 1' # 每周
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['javascript', 'python']
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
name: Dependency Check
on:
push:
branches: [main]
schedule:
- cron: '0 0 * * 1'
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm audit --audit-level=moderate
- run: npx snyk test
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
continue-on-error: true
name: Container Security Scan
on:
push:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t myapp:${{ github.sha }} .
- uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
在 .github/actions/ 中创建可重用的操作。
.github/actions/setup-project/action.yml:
name: 'Setup Project'
description: 'Install dependencies and cache'
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 }}
cache: 'npm'
- run: npm ci
shell: bash
用法:
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
with:
node-version: '20'
.github/workflows/reusable-deploy.yml:
name: Reusable Deploy
on:
workflow_call:
inputs:
environment:
required: true
type: string
secrets:
deploy-token:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.deploy-token }}
ENVIRONMENT: ${{ inputs.environment }}
用法:
name: Deploy Production
on:
push:
branches: [main]
jobs:
deploy:
uses: ./.github/workflows/reusable-deploy.yml
with:
environment: production
secrets:
deploy-token: ${{ secrets.PRODUCTION_TOKEN }}
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- uses: docker/build-push-action@v5
with:
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
jobs:
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint
test-unit:
runs-on: ubuntu-latest
steps:
- run: npm run test:unit
test-integration:
runs-on: ubuntu-latest
steps:
- run: npm run test:integration
# 全部并行运行
jobs:
deploy:
# 在草稿 PR 上跳过部署
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
设置仓库密钥:
ACTIONS_RUNNER_DEBUG: trueACTIONS_STEP_DEBUG: true- name: Debug Info
run: |
echo "Event: ${{ github.event_name }}"
echo "Ref: ${{ github.ref }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
env
- name: Setup tmate session
if: failure()
uses: mxschmitt/action-tmate@v3
timeout-minutes: 15
uses: actions/checkout@8e5e7e5a...continue-on-error- name: Comment on PR
if: failure() && github.event_name == 'pull_request'
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: '❌ Tests failed. Please check the workflow logs.'
})
name: Auto-merge Dependabot
on:
pull_request:
types: [opened, synchronize]
jobs:
auto-merge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
- uses: gh enable-auto-merge --merge
if: success()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Slack Notification
if: always()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Deploy to ${{ inputs.environment }}: ${{ job.status }}'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
工作流未触发:
.github/workflows/ 目录下作业被跳过:
if 条件needs 依赖项已成功超时:
timeout-minutes: 30权限被拒绝:
更新工作流权限:
permissions:
contents: write
pull-requests: write
密钥不可用:
astral-sh/setup-uv@v3 和 uv python install 3.11。uv sync --dev 并运行 uv run ruff、uv run mypy、uv run pytest。pnpm/action-setup@v4 和 actions/setup-node@v4 并启用 pnpm 缓存。pnpm install --frozen-lockfile 安装,然后运行 pnpm run lint、pnpm run build:types、pnpm test。push 标签 v* 时触发。pypa/gh-action-pypi-publish@release/v1 或 NODE_AUTH_TOKEN 进行 npm 发布。workflow_run 时触发。HOMEBREW_TAP_TOKEN 运行 scripts/update_homebrew_formula.py。每周安装数
200
仓库
GitHub Actions is GitHub's native CI/CD platform for automating software workflows. Define workflows in YAML files to build, test, and deploy code directly from your repository with event-driven automation.
Create .github/workflows/test.yml:
name: Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
YAML files in .github/workflows/ that define automation pipelines.
Structure :
Name : Workflow identifier
Triggers : Events that start the workflow
Jobs : One or more jobs to execute
Steps : Commands/actions within each job
name: CI Pipeline on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: echo "Building project"
Independent execution units that run in parallel by default.
jobs:
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint
test:
runs-on: ubuntu-latest
needs: lint # Wait for lint to complete
steps:
- run: npm test
deploy:
runs-on: ubuntu-latest
needs: [lint, test] # Wait for both
steps:
- run: ./deploy.sh
Sequential commands or actions within a job.
steps:
# Use pre-built action
- uses: actions/checkout@v4
# Run shell command
- run: npm install
# Named step with environment
- name: Run tests
run: npm test
env:
NODE_ENV: test
Reusable units of code (from marketplace or custom).
# Official action
- uses: actions/checkout@v4
# Third-party action
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: user/app:latest
# Local action
- uses: ./.github/actions/custom-action
on:
push:
branches:
- main
- 'releases/**' # Wildcard pattern
tags:
- 'v*' # All version tags
paths:
- 'src/**'
- '!src/docs/**' # Exclude docs
on:
pull_request:
types: [opened, synchronize, reopened]
branches: [main, develop]
paths-ignore:
- '**.md'
- 'docs/**'
on:
schedule:
# Every day at 2:30 AM UTC
- cron: '30 2 * * *'
# Every Monday at 9:00 AM UTC
- cron: '0 9 * * 1'
on:
workflow_dispatch:
inputs:
environment:
description: 'Deployment environment'
required: true
type: choice
options:
- staging
- production
version:
description: 'Version to deploy'
required: false
default: 'latest'
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 0' # Weekly
workflow_dispatch: # Manual
env:
NODE_ENV: production
API_URL: https://api.example.com
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo $NODE_ENV
jobs:
test:
runs-on: ubuntu-latest
env:
TEST_DATABASE: test_db
steps:
- run: pytest
steps:
- name: Build
run: npm run build
env:
BUILD_TARGET: production
Store sensitive data in repository settings.
steps:
- name: Deploy
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
Best Practices :
Repository and workflow information.
steps:
- name: Print context
run: |
echo "Repository: ${{ github.repository }}"
echo "Ref: ${{ github.ref }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
echo "Event: ${{ github.event_name }}"
echo "Branch: ${{ github.ref_name }}"
Access environment variables.
env:
BUILD_ID: 12345
steps:
- run: echo "Build ${{ env.BUILD_ID }}"
Access repository secrets.
- run: echo "Token exists"
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
Access matrix values.
strategy:
matrix:
node: [18, 20, 22]
steps:
- run: echo "Testing Node ${{ matrix.node }}"
Access outputs from dependent jobs.
jobs:
build:
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- id: get_version
run: echo "version=1.2.3" >> $GITHUB_OUTPUT
deploy:
needs: build
steps:
- run: echo "Deploying ${{ needs.build.outputs.version }}"
jobs:
ubuntu:
runs-on: ubuntu-latest # ubuntu-22.04
macos:
runs-on: macos-latest # macOS 14
windows:
runs-on: windows-latest # Windows 2022
specific:
runs-on: ubuntu-20.04 # Specific version
Available Runners :
ubuntu-latest, ubuntu-22.04, ubuntu-20.04macos-latest, macos-14, macos-13windows-latest, windows-2022, windows-2019runs-on: self-hosted
# With labels
runs-on: [self-hosted, linux, x64, gpu]
Setup :
Test across multiple versions.
strategy:
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
strategy:
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
include:
# Add specific combination
- node: 22
os: macos-latest
experimental: true
exclude:
# Remove specific combination
- node: 18
os: windows-latest
strategy:
fail-fast: false # Continue other jobs if one fails
matrix:
node: [18, 20, 22]
strategy:
max-parallel: 2 # Run only 2 jobs concurrently
matrix:
node: [18, 20, 22]
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for changelog
submodules: true # Include submodules
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # or 'yarn', 'pnpm'
registry-url: 'https://registry.npmjs.org'
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'maven'
- uses: actions/setup-go@v5
with:
go-version: '1.21'
cache: true
- uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
steps:
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: ./deploy.sh
- name: Deploy to staging
if: github.ref == 'refs/heads/develop'
run: ./deploy-staging.sh
- name: Only on PR
if: github.event_name == 'pull_request'
run: echo "This is a PR"
- name: On success
if: success()
run: echo "Previous steps succeeded"
- name: On failure
if: failure()
run: echo "A step failed"
- name: Always run
if: always()
run: echo "Cleanup tasks"
jobs:
deploy:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
name: Node.js CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run type-check
- run: npm test
env:
CI: true
- run: npm run build
- uses: codecov/codecov-action@v4
if: matrix.node-version == 20
with:
token: ${{ secrets.CODECOV_TOKEN }}
name: Python CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- run: pip install -r requirements.txt
- run: pip install pytest pytest-cov mypy ruff
- run: ruff check .
- run: mypy .
- run: pytest --cov=. --cov-report=xml
- uses: codecov/codecov-action@v4
if: matrix.python-version == '3.11'
name: Docker Build
on:
push:
branches: [main]
tags: ['v*']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: user/app
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
name: Next.js CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run build
- run: npm test
deploy-preview:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
deploy-production:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
name: Deploy to Netlify
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run build
- uses: netlify/actions/cli@master
with:
args: deploy --prod --dir=dist
env:
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
name: Deploy to AWS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run build
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- run: aws s3 sync dist/ s3://${{ secrets.S3_BUCKET }} --delete
- run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \
--paths "/*"
name: Publish Docker Image
on:
release:
types: [published]
jobs:
push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}
name: Test Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test -- --coverage
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/coverage-final.json
fail_ci_if_error: true
name: Integration Tests
on: [push, pull_request]
jobs:
integration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run test:integration
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
REDIS_URL: redis://localhost:6379
name: E2E Tests
on: [push, pull_request]
jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx playwright install --with-deps
- run: npm run build
- run: npm run test:e2e
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for changelog
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
name: Create Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: changelog
run: |
# Generate changelog from commits
CHANGELOG=$(git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:"- %s (%h)" --no-merges)
echo "changelog<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
release_name: Release ${{ github.ref_name }}
body: |
## Changes
${{ steps.changelog.outputs.changelog }}
draft: false
prerelease: false
name: Publish to npm
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm test
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 1' # Weekly
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['javascript', 'python']
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
name: Dependency Check
on:
push:
branches: [main]
schedule:
- cron: '0 0 * * 1'
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm audit --audit-level=moderate
- run: npx snyk test
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
continue-on-error: true
name: Container Security Scan
on:
push:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t myapp:${{ github.sha }} .
- uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
Create reusable actions in .github/actions/.
.github/actions/setup-project/action.yml:
name: 'Setup Project'
description: 'Install dependencies and cache'
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 }}
cache: 'npm'
- run: npm ci
shell: bash
Usage :
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
with:
node-version: '20'
.github/workflows/reusable-deploy.yml:
name: Reusable Deploy
on:
workflow_call:
inputs:
environment:
required: true
type: string
secrets:
deploy-token:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.deploy-token }}
ENVIRONMENT: ${{ inputs.environment }}
Usage :
name: Deploy Production
on:
push:
branches: [main]
jobs:
deploy:
uses: ./.github/workflows/reusable-deploy.yml
with:
environment: production
secrets:
deploy-token: ${{ secrets.PRODUCTION_TOKEN }}
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- uses: docker/build-push-action@v5
with:
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
jobs:
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint
test-unit:
runs-on: ubuntu-latest
steps:
- run: npm run test:unit
test-integration:
runs-on: ubuntu-latest
steps:
- run: npm run test:integration
# All run in parallel
jobs:
deploy:
# Skip deploy on draft PRs
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
Set repository secrets:
ACTIONS_RUNNER_DEBUG: trueACTIONS_STEP_DEBUG: true- name: Debug Info
run: |
echo "Event: ${{ github.event_name }}"
echo "Ref: ${{ github.ref }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
env
- name: Setup tmate session
if: failure()
uses: mxschmitt/action-tmate@v3
timeout-minutes: 15
uses: actions/checkout@8e5e7e5a...continue-on-error strategically- name: Comment on PR
if: failure() && github.event_name == 'pull_request'
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: '❌ Tests failed. Please check the workflow logs.'
})
name: Auto-merge Dependabot
on:
pull_request:
types: [opened, synchronize]
jobs:
auto-merge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
- uses: gh enable-auto-merge --merge
if: success()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Slack Notification
if: always()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Deploy to ${{ inputs.environment }}: ${{ job.status }}'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
Workflow not triggering :
.github/workflows/Job skipped :
if conditionsneeds dependencies succeededTimeout :
timeout-minutes: 30Permission denied :
Update workflow permissions:
permissions:
contents: write
pull-requests: write
Secrets not available :
astral-sh/setup-uv@v3 and uv python install 3.11.uv sync --dev and run uv run ruff, uv run mypy, uv run pytest.pnpm/action-setup@v4 and actions/setup-node@v4 with pnpm cache.pnpm install --frozen-lockfile, then pnpm run lint, pnpm run build:types, pnpm test.push tags v*.pypa/gh-action-pypi-publish@release/v1 or NODE_AUTH_TOKEN for npm publish.workflow_run after CI success.scripts/update_homebrew_formula.py with HOMEBREW_TAP_TOKEN.Weekly Installs
200
Repository
GitHub Stars
18
First Seen
Jan 23, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode174
codex163
gemini-cli160
claude-code156
github-copilot150
cursor146
Azure Data Explorer (Kusto) 查询技能:KQL数据分析、日志遥测与时间序列处理
102,600 周安装
阿里云AnalyticDB MySQL管理指南:使用OpenAPI与SDK进行云数据库操作
249 周安装
Google App Engine 部署指南:标准与灵活环境配置、Cloud SQL 连接教程
249 周安装
HTMX 开发指南:无需复杂 JavaScript 构建动态 Web 应用 | 现代前端技术
249 周安装
Hugging Face CLI 命令大全:hf 终端工具下载、上传、管理模型与数据集
249 周安装
e-Tax 电子申报自动化技能:通过浏览器自动填写日本国税厅申报书创建专区
249 周安装
数据库架构师技能:设计可扩展高性能数据层,精通技术选型与数据建模
249 周安装