diff --git a/.github/workflows/trigger-woodpecker-pipeline.yml b/.github/workflows/trigger-woodpecker-pipeline.yml new file mode 100644 index 0000000..e693a92 --- /dev/null +++ b/.github/workflows/trigger-woodpecker-pipeline.yml @@ -0,0 +1,73 @@ +name: Trigger a Woodpecker CI/CD pipeline + +on: + workflow_call: + inputs: + api-url: + description: > + Base URL of the Woodpecker instance, e.g. https://ci.example.com. + --api-url parameter for the woodpecker-trigger.sh script. + required: true + type: string + owner: + description: > + Repository owner (user or organization). + --owner parameter for the woodpecker-trigger.sh script. + required: true + type: string + repo: + description: > + Repository name. + --repo parameter for the woodpecker-trigger.sh script. + required: true + type: string + ref: + description: > + Branch to trigger the pipeline on. + --ref parameter for the woodpecker-trigger.sh script. + required: false + type: string + default: 'main' + inputs: + description: > + Additional --input flags to pass to woodpecker-trigger.sh, e.g. + "--input KEY=VALUE --input KEY2=VALUE2". Keys must be valid shell + variable names (no hyphens). + required: false + type: string + default: '' + secrets: + woodpecker-token: + description: > + Woodpecker API token for triggering the pipeline. + --token parameter for the woodpecker-trigger.sh script. + required: true + +jobs: + trigger-woodpecker: + runs-on: ubuntu-latest + name: Trigger a Woodpecker CI/CD pipeline + permissions: + contents: read + steps: + - uses: actions/checkout@v6 + with: + repository: TrenchBoot/.github + path: shared + ref: ${{ job.workflow_sha }} + - name: Trigger Woodpecker CI/CD pipeline + env: + WOODPECKER_TOKEN: ${{ secrets.woodpecker-token }} + WOODPECKER_API_URL: ${{ inputs.api-url }} + WOODPECKER_OWNER: ${{ inputs.owner }} + WOODPECKER_REPO: ${{ inputs.repo }} + WOODPECKER_REF: ${{ inputs.ref }} + WOODPECKER_INPUTS: ${{ inputs.inputs }} + run: | + shared/scripts/woodpecker-trigger.sh \ + --token "$WOODPECKER_TOKEN" \ + --api-url "$WOODPECKER_API_URL" \ + --owner "$WOODPECKER_OWNER" \ + --repo "$WOODPECKER_REPO" \ + --ref "$WOODPECKER_REF" \ + $WOODPECKER_INPUTS diff --git a/scripts/woodpecker-trigger.sh b/scripts/woodpecker-trigger.sh new file mode 100755 index 0000000..ff84315 --- /dev/null +++ b/scripts/woodpecker-trigger.sh @@ -0,0 +1,214 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: 2026 3mdeb +# +# SPDX-License-Identifier: Apache-2.0 + +trap cleanup EXIT +set -euo pipefail + +usage() { + cat <&2 + return 1 + ;; + esac +} + +# Prints the architecture component of the woodpecker-cli binary name. +# Return codes: +# 0: Success. +# 1: Unsupported architecture. +detect_arch() { + case "$(uname -m)" in + x86_64) echo "amd64" ;; + aarch64|arm64) echo "arm64" ;; + armv7l) echo "arm-7" ;; + i386|i686) echo "386" ;; + *) + echo "ERROR: Unsupported architecture: $(uname -m)" >&2 + return 1 + ;; + esac +} + +# Downloads the woodpecker-cli binary for the current platform to a temporary +# directory. Sets the global WP_BIN and WP_TMPDIR variables. +# Return codes: +# 0: Success. +# 1: Download or platform detection failed. +download_woodpecker_cli() { + local version="$1" + local os arch filename url + + os="$(detect_os)" + arch="$(detect_arch)" + WP_TMPDIR="$(mktemp -d)" + WP_BIN="${WP_TMPDIR}/woodpecker-cli" + + filename="woodpecker-cli_${os}_${arch}.tar.gz" + url="https://github.com/woodpecker-ci/woodpecker/releases/download/v${version}/${filename}" + + echo "Downloading woodpecker-cli v${version} (${os}/${arch})..." + curl -sL --fail -o "${WP_TMPDIR}/${filename}" "$url" || { + echo "ERROR: Failed to download woodpecker-cli from: ${url}" >&2 + return 1 + } + tar -xzf "${WP_TMPDIR}/${filename}" -C "$WP_TMPDIR" woodpecker-cli + chmod +x "$WP_BIN" +} + + +# Pinned woodpecker-cli version. Override with the WOODPECKER_CLI_VERSION +# environment variable. +# Check https://github.com/woodpecker-ci/woodpecker/releases for available +# versions. +WOODPECKER_CLI_VERSION="${WOODPECKER_CLI_VERSION:-3.13.0}" +WP_BIN="" +WP_TMPDIR="" +TOKEN="" +API_URL="" +OWNER="" +REPO="" +REF="main" +INPUTS=() + +parse_args() { + while [[ $# -gt 0 ]]; do + case $1 in + -v|--verbose) + set -x + shift + ;; + -h|--help) + usage + exit 0 + ;; + -t|--token) + TOKEN="$2" + shift 2 + ;; + -u|--api-url) + API_URL="$2" + shift 2 + ;; + -o|--owner) + OWNER="$2" + shift 2 + ;; + -r|--repo) + REPO="$2" + shift 2 + ;; + --ref) + REF="$2" + shift 2 + ;; + --input) + INPUTS+=("$2") + shift 2 + ;; + -*) + echo "ERROR: Unknown option $1" >&2 + usage + exit 1 + ;; + *) + echo "ERROR: Unexpected argument '$1'" >&2 + usage + exit 1 + ;; + esac + done +} + +parse_args "$@" + +# Validate required parameters: +errors=0 +[[ -z "$TOKEN" ]] && { echo "ERROR: --token is required." >&2; errors=$((errors+1)); } +[[ -z "$API_URL" ]] && { echo "ERROR: --api-url is required." >&2; errors=$((errors+1)); } +[[ -z "$OWNER" ]] && { echo "ERROR: --owner is required." >&2; errors=$((errors+1)); } +[[ -z "$REPO" ]] && { echo "ERROR: --repo is required." >&2; errors=$((errors+1)); } +if [[ $errors -gt 0 ]]; then + usage + exit 1 +fi + +# Strip trailing slash from API_URL: +API_URL="${API_URL%/}" + +# Download woodpecker-cli and register cleanup on exit: +download_woodpecker_cli "$WOODPECKER_CLI_VERSION" + +# Build the pipeline create command. +cmd=("$WP_BIN" pipeline create "${OWNER}/${REPO}" --branch "$REF") +for var in "${INPUTS[@]}"; do + cmd+=(--var "$var") +done + +echo "Triggering pipeline for ${OWNER}/${REPO} on branch '${REF}'..." +WOODPECKER_SERVER="$API_URL" WOODPECKER_TOKEN="$TOKEN" "${cmd[@]}" + +echo "Pipeline triggered successfully."