writing-woodpecker-ci について
GitHub Actions や Semaphore CI のパイプラインを Woodpecker CI に移行する CI/CD エンジニア向けスキルです。Docker ベースのステップ設定、ワークフローの依存関係、主な構文の違いを解説します。
主な機能
- 01GitHub Actions の移行対照表
- 02Semaphore CI の移行対照表
- 03Woodpecker YAML 構文ガイド
- 04ワークフロー依存関係と並列実行
- 05マトリックス、サービス、キャッシュ設定
活用シーン
- 01GitHub Actions のワークフローを Woodpecker CI に移行
- 02Semaphore CI のパイプラインを Woodpecker CI に変換
- 03複数ファイルのワークフロー依存関係と並列実行を設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ beecode-rs/ claude-skills --skill writing-woodpecker-ciインストール後、Claude Code で/writing-woodpecker-ciを入力して読み込まれたか確認します。
同梱ファイルLICENSE.txt
詳細
Woodpecker CI パイプライン移行エキスパート
GitHub Actions と Semaphore CI から Woodpecker CI へのパイプライン移行を専門とする、CI/CD エンジニアです。Woodpecker は Docker を第一に考えた、コミュニティ主導の CI エンジン(Drone からフォーク)で、パイプラインの各ステップを分離されたコンテナ内で実行します。
この Docker ネイティブの考え方を理解することが、適切な移行の鍵です。設定すべき「ランナー」や「エージェント」はありません。各ステップに Docker イメージを指定すれば、あとはそれに従って実行されます。
.woodpecker.yml の構造
steps:
build-step-name:
image: alpine:latest # REQUIRED: Docker image for this step
commands: # Shell commands to run inside the container
- echo "Hello World"
environment: # Step-level env vars
FOO: bar
secrets: [github_token] # Injected from Woodpecker UI/CLI secrets
when: # Conditional execution
- event: push
branch: main
plugin-step-name:
image: woodpeckerci/plugin-docker-buildx:latest
settings: # Passed as PLUGIN_-prefixed env vars to the plugin
repo: myorg/myrepo
tags: latest
覚えておくべき重要な点:
- 各ステップに
image:が必要です — 共有のランナー環境はありません commands:はコンテナ内でシェルを実行します — 標準的な Linux ツールを利用できますsettings:はプラグイン専用です — 自動的にPLUGIN_*環境変数になります- Woodpecker はデフォルトでリポジトリをクローンします — チェックアウトのステップは不要です(GHA とは異なります)
- ステップは辞書形式(キーに名前を指定)または
- name:を使ったリスト形式でも定義できます — どちらも有効です
ファイル構成
単一ファイル(シンプルなプロジェクト)
リポジトリのルートに .woodpecker.yml を配置します。Woodpecker はワークフローを 1 つ持つパイプラインを 1 つ作成します。
複数ファイル(実際のプロジェクトに推奨)
YAML ファイルを .woodpecker/ ディレクトリに配置します。各ファイルは独立したワークフローとなり、それぞれ別のエージェント上で並列に実行されます。
.woodpecker/
├── build.yaml
├── test.yaml # depends_on: [build]
├── lint.yaml # runs in parallel with build
└── deploy.yaml # depends_on: [lint, build, test]
各ワークフローはそれぞれのステータスを forge(GitHub/Gitea など)に報告するため、より迅速にフィードバックを得られます。テストの実行中に lint が失敗することもあります。
特に注意すべき点: ファイルが共有されるのは、同じワークフロー内のステップ間のみです。build.yaml が生成するアーティファクトを deploy.yaml が必要とする場合は、ストレージプラグイン(例:S3)を使ってワークフロー間で受け渡してください。これは、ジョブ間でアーティファクトを受け渡せる GHA とは異なります。
移行チートシート
GitHub Actions → Woodpecker CI
| GitHub Actions | Woodpecker CI | 備考 |
|---|---|---|
.github/workflows/*.yml | .woodpecker.yml または .woodpecker/*.yaml | 単一ファイル、またはワークフローを格納するディレクトリ |
on: [push, pull_request] | ステップまたはワークフローごとの when: | 条件はパイプライン単位ではなく、ステップ単位で評価されます |
jobs.<id>.steps[] | steps: | 直接対応します |
runs-on: ubuntu-latest | (削除) | ランナーはありません — 各ステップに image: を指定します |
uses: actions/checkout@v3 | (通常は不要) | Woodpecker が自動でクローンします。特別なケースでは clone: ブロックを使います |
uses: action/repo@v1 | image: plugin/repo:latest | GHA Actions には互換性がありません — Woodpecker プラグインを探すか、コマンドとして書き直してください |
with:(アクションの入力) | settings: | プラグイン専用です。PLUGIN_* 環境変数になります |
env: | environment: | ステップレベルまたはパイプラインレベルで使用できます |
secrets: GH_TOKEN | secrets: [gh_token] | 環境変数として自動的に注入されます |
if: github.ref == 'main' | when: [branch: main] | 下記の when 構文を参照してください |
needs: [build] | depends_on: [build] | ワークフローレベル(ファイル間)とステップレベル(ワークフロー内)の両方で使用できます |
strategy.matrix | matrix: | マトリックス変数は環境変数として注入されます |
services: | services: | リンクされた Docker コンテナです。ホスト名はサービス名になります |
actions/cache | volumes: | ステップ間の永続化のためにホストパスをマウントします |
continue-on-error: true | failure: ignore | ワークフローを失敗させずにステップを失敗させられます |
コミット内の [skip ci] | [SKIP CI] または [CI SKIP] | 大文字と小文字は区別されません |
Semaphore CI → Woodpecker CI
| Semaphore CI | Woodpecker CI | 備考 |
|---|---|---|
.semaphore/semaphore.yml | .woodpecker.yml | |
blocks: | steps: | Semaphore のブロックは Woodpecker のステップに対応します |
task: | steps.[name]: | |
agent.machine.type: | (削除) | サーバー上の Woodpecker エージェント設定で処理されます |
prologue: / epilogue: | 最初/最後のステップ | setup または teardown という名前のステップを追加します |
promotions: | depends_on を指定した workflows: | DAG ベースのデプロイパイプラインです |
secrets:(設定内) | secrets: [name] | UI/CLI で管理し、名前で参照します |
構文リファレンス
when ブロック(条件)
Woodpecker では、リスト項目内の条件は論理 AND、リスト項目間の条件は論理 OR として扱われます。これはステップ単位と、ワークフロー全体をスキップするグローバルなワークフロー単位の両方に適用されます。
使用可能なイベント: push、pull_request、pull_request_closed、pull_request_metadata、tag、release、deployment、cron、manual
when:
# Run on push to main OR dev
- event: push
branch: [main, dev]
# Run on pull requests to main
- event: pull_request
branch: main
# Only on specific cron job
- event: cron
cron: sync_* # glob pattern on cron job name
# Only for tags starting with 'v'
- event: tag
ref: refs/tags/v*
# Path filtering (only on push and pull_request events)
- event: push
path:
include: ['src/**/*.go', 'go.mod']
exclude: ['**_test.go']
ignore_message: '[ALL]' # skip path filter if commit msg contains this
on_empty: true # treat empty file list as match (default: true)
# Run even on failure (e.g., for notifications)
- status: [failure]
# Custom expression evaluation
- evaluate: 'CI_COMMIT_AUTHOR == "woodpecker-ci"'
その他の when フィルター:
repo: owner/name— 特定のリポジトリのみplatform: linux/amd64— 特定のエージェントプラットフォームのみ(マトリックスビルドと併用)instance: ci.example.com— 特定の Woodpecker サーバーのみmatrix: { GO_VERSION: 1.5 }— 特定のマトリックスの組み合わせのみ
グローバルワークフローの when — 条件に基づいてワークフロー全体をスキップします。steps: の前に、トップレベルに配置します。
when:
branch: main
steps:
- name: deploy
image: alpine
commands: echo "deploying..."
ワークフロー(DAG/並列処理)
ワークフロー間(複数ファイル):ファイルを .woodpecker/ に配置し、トップレベルで depends_on を使用します。depends_on に指定する名前は、拡張子を除いたファイル名です。
# .woodpecker/deploy.yaml
depends_on:
- lint
- build
- test
steps:
- name: deploy
image: alpine
commands: echo "deploying..."
依存先が失敗してもワークフローを実行するには:
depends_on:
- deploy
runs_on: [success, failure] # default is [success] only
1 つのワークフロー内のステップ間 — 個々のステップで depends_on を使用して DAG を作成します。いずれかのステップに depends_on を設定すると、設定されていない他のすべてのステップは直ちに並列実行されます。
steps:
- name: build # runs immediately
image: golang:1.21
commands: go build ./...
- name: test # runs immediately (no depends_on)
image: golang:1.21
commands: go test ./...
- name: deploy # waits for both build AND test
image: alpine
commands: echo "deploying..."
depends_on: [build, test]
- name: check-format # runs immediately (empty depends_on forces parallel)
image: mstruebing/editorconfig-checker
depends_on: []
ステップのオプション
steps:
- name: build
image: golang:1.21
pull: true # always pull latest image (default: only if not present)
commands:
- go build
- go test
environment: # step-level env vars (can't expand variables here)
CGO: 0
GOOS: linux
failure: ignore # allow failure without failing workflow (like continue-on-error)
# failure: cancel # alternative: cancel the whole pipeline on failure
directory: ./subdir # run commands in a subdirectory
when:
- event: push
# detach: true # run step in background until workflow finishes
# privileged: true # escalated capabilities (trusted repos only)
# backend_options: # backend-specific options (Docker user/group, K8s service account)
# kubernetes:
# serviceAccountName: my-sa
クローンのカスタマイズ
Woodpecker はリポジトリを自動的にクローンします。必要に応じて、クローンの動作を上書きまたはスキップできます。
# Skip cloning entirely (e.g., notification-only workflows)
skip_clone: true
# Customize clone behavior
clone:
git:
image: woodpeckerci/plugin-git
settings:
depth: 50
partial: false
# Clone submodules with SSH-to-HTTPS override
clone:
git:
image: woodpeckerci/plugin-git
settings:
recursive: true
submodule_override:
my-module: https://github.com/octocat/my-module.git
ワークスペース
ワークフロー内のすべてのステップは、同じワークスペース(マウントされたボリューム)を共有します。デフォルトのパスは /woodpecker/src/{host}/{owner}/{repo} です。
workspace:
base: /go
path: src/github.com/octocat/hello-world
steps:
- name: build
image: golang:latest
commands:
- go get
- go build
サービス(データベースなど)
services:
database:
image: postgres:15
environment:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
steps:
- name: test
image: alpine
commands:
- ping -c 1 database # Hostname = service name
ボリューム(キャッシュ)
steps:
- name: restore-cache
image: alpine
commands:
- ls -l /cache
volumes:
- /tmp/cache:/cache # host:container
- name: build
image: golang:1.21
volumes:
- /tmp/cache:/cache
commands:
- go build -o /cache/app ./...
マトリックスビルド
マトリックス変数は環境変数として注入されます。Woodpecker は組み合わせごとに個別のビルドを実行します。
steps:
test:
image: golang:${GO_VERSION}
commands:
- go test
matrix:
GO_VERSION: ["1.19", "1.20", "1.21"]
ラベル(エージェントの選択)
ラベルを照合して、ワークフローを実行するエージェントを選択します。
labels:
platform: linux/arm64 # only run on arm64 agents
location: europe # custom label — agent must have this set
steps:
- name: build
image: golang
commands: go build
デフォルトのエージェントラベル:platform={os}/{arch}、hostname={name}、backend=docker、repo=*。値が空のラベルは無視されます。
環境変数
Woodpecker は実行時に組み込み変数を注入します。これらの変数は environment: ブロックで上書きできません。
よく使用する変数
| 変数 | 説明 | 例 |
|---|---|---|
CI_REPO | owner/name | john-doe/my-repo |
CI_REPO_OWNER | リポジトリの所有者 | john-doe |
CI_REPO_NAME | リポジトリ名 | my-repo |
CI_REPO_DEFAULT_BRANCH | デフォルトブランチ | main |
CI_COMMIT_SHA | 完全なコミット SHA | eba09b46... |
CI_COMMIT_BRANCH | ブランチ名 | main |
CI_COMMIT_TAG | タグ名(タグイベント以外では空) | v1.10.3 |
CI_COMMIT_MESSAGE | コミットメッセージ | Initial commit |
CI_COMMIT_AUTHOR | 作成者のユーザー名 | john-doe |
CI_COMMIT_PULL_REQUEST | PR 番号(PR イベントのみ) | 42 |
CI_COMMIT_PULL_REQUEST_LABELS | PR ラベル(PR イベントのみ) | bug,server |
CI_PIPELINE_EVENT | イベントの種類 | push、pull_request、tag、release、cron、manual、deployment |
CI_PIPELINE_NUMBER | パイプライン番号 | 8 |
CI_PIPELINE_URL | CI UI 上のパイプラインへのリンク | https://ci.example.com/repos/7/pipeline/8 |
CI_PIPELINE_FILES | 変更されたファイル(push/PR イベント、最大 500 件) | [".woodpecker.yml","README.md"] |
CI_WORKFLOW_NAME | ワークフロー名(拡張子を除いたファイル名) | build |
CI_STEP_NAME | 現在のステップ名 | build package |
CI_FORGE_TYPE | フォージ名 | github、gitea、gitlab、forgejo、bitbucket |
CI_SYSTEM_VERSION | Woodpecker サーバーのバージョン | 2.7.0 |
前回のパイプラインの変数
通知ロジックや実行結果の比較に役立ちます。
| 変数 | 説明 |
|---|---|
CI_PREV_PIPELINE_STATUS | success または failure |
CI_PREV_COMMIT_SHA | 前回のコミット SHA |
CI_PREV_PIPELINE_NUMBER | 前回のパイプライン番号 |
文字列置換
settings:、commands:、when: ブロックでは ${VAR} を使用します。
settings:
target: /target/${CI_COMMIT_SHA} # full SHA
target: /target/${CI_COMMIT_SHA:0:8} # first 8 chars
target: /target/${CI_COMMIT_TAG##v} # strip 'v' prefix: v1.0.0 → 1.0.0
Bash 形式の文字列操作: ${param,}(先頭を小文字にする)、${param^^}(大文字にする)、${param:pos:len}(部分文字列)、${param##prefix}(プレフィックスを削除する)、${param%%suffix}(サフィックスを削除する)、${param/old/new}(置換する)、${param=default}(デフォルト値)。
重要: commands: では、前処理を防ぐためにドル記号をエスケープします。実行時にシェルで変数を処理する場合は、${PATH} ではなく $${PATH} を使用してください。
環境変数に関する注意点
environment:では変数を展開できません。代わりにcommands:でexportを使用してください- Woodpecker サーバーの設定
WOODPECKER_ENVIRONMENT=KEY:val,KEY2:val2でグローバルな環境変数を設定します
不足している機能への対処
GitHub Action に対応する Woodpecker プラグインがない場合 — 適切なイメージ(例:alpine、python:3、node:18)内の標準 Linux ツールを使用して、commands: でロジックを書き換えます。たとえば、actions/setup-node の代わりに、image: node:18 を使用します。
GitHub コンテキスト変数が必要な場合 — 上記の CI_* 環境変数を使用します。github.event_name に相当するのは CI_PIPELINE_EVENT、github.ref に相当するのは CI_COMMIT_REF などです。
コミットからビルドをスキップする場合 — コミットメッセージに [SKIP CI] または [CI SKIP] を追加します(大文字と小文字は区別されません)。
Drone CI のテクニックが使える場合 — Woodpecker は Drone のフォークなので、Drone に関する StackOverflow の回答がそのまま使えることがよくあります。
調査に役立つリソース
ここで説明されていない特殊なケースに遭遇した場合は、次の情報を参照してください。
- ワークフロー構文: https://woodpecker-ci.org/docs/usage/workflow-syntax
- ワークフロー(複数ファイル): https://woodpecker-ci.org/docs/usage/workflows
- 環境変数: https://woodpecker-ci.org/docs/usage/environment
- プラグインマーケットプレイス: https://woodpecker-ci.org/plugins — GHA の
uses:アクションに代わる Docker イメージを検索できます - Drone からの移行: https://woodpecker-ci.org/docs/migration/drone
- ローカルテスト:
woodpecker-cli exec .woodpecker.yml
必要なアクションに対応するプラグインがない場合、無理に使おうとせず、標準イメージを使った明確な commands: ステップを記述してください。部分的にしか合わないプラグインを探すより、そのほうがすっきりすることがよくあります。