A production-ready collection of reusable composite GitHub Actions for Zondax projects, designed for enterprise-scale CI/CD workflows with comprehensive security, testing, and performance optimization.
# In your workflow file (.github/workflows/ci.yml)
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout with App Auth
uses: zondax/checkout-with-app@v1
with:
github_app_auth: true
app_id: ${{ secrets.APP_ID }}
app_pem: ${{ secrets.APP_PEM }}
- name: Setup Node.js
uses: zondax/setup-node-env@v1
with:
node_version: '20'
package_manager: 'pnpm'
- name: Setup Ubuntu Packages
uses: zondax/setup-ubuntu-packages@v1
with:
packages: "build-essential cmake pkg-config libssl-dev"Checkout repository with optional GitHub App authentication and git configuration.
Usage:
- uses: zondax/checkout-with-app@v1
with:
github_app_auth: true
github_app_repos: |
owner/repo1
owner/repo2
app_id: ${{ secrets.APP_ID }}
app_pem: ${{ secrets.APP_PEM }}Inputs:
github_app_auth: Use GitHub App Token (default: false)github_app_repos: Additional repositories to access (one per line)checkout_submodules: Checkout submodules (default: true)fetch_depth: Number of commits to fetch. 0 fetches all history (default: 0)ref: The branch, tag or SHA to checkoutuse_sudo: Use sudo for git config command (default: false)patch_git_config: Add safe.directory to git config (default: true)app_id: GitHub App IDapp_pem: GitHub App PEM
Setup Node.js with package manager (npm, yarn, pnpm, or bun) and install dependencies.
Usage:
- uses: zondax/setup-node-env@v1
with:
node_version: '20'
package_manager: 'pnpm'
package_manager_version: '8.0.0'
autoinit_env: trueInputs:
node_version: Node.js version to install (default: lts/*)package_manager: Package manager to use - npm, yarn, pnpm, or bun (default: npm)package_manager_version: Package manager version (default: latest)install_deps: Install dependencies after setup (default: true)working_directory: Working directory for package operations (default: .)cache_dependencies: Cache dependencies (default: true)autoinit_env: Run env:init:ci script after installing dependencies (default: false)
Outputs:
pm: Package manager command (e.g., 'pnpm')pm_run: Package manager run command (e.g., 'pnpm run')cache_hit: Whether the cache was hit
Configure Ubuntu mirrors and install packages for faster, reliable CI builds.
Usage:
- uses: zondax/setup-ubuntu-packages@v1
with:
packages: |
- git
- curl
- build-essential
- pkg-config
- libssl-dev
extra_packages: |
- jq
- unzipInputs:
packages: List of packages to install as YAML list or space-separated string (default: git, curl)extra_packages: Additional packages to install as YAML list or space-separated string (default: '')
Advanced Inputs (optional):
update_cache: Run apt-get update before package installation (default: true)ubuntu_version: Ubuntu version codename, auto-detected if empty (default: '')retry_count: Number of retry attempts for package installation (default: 3)cache_timeout: Timeout in seconds for package operations (default: 300)
Note: Mirror configuration is handled automatically using fast mirrors (Init7) with fallback to official Ubuntu repositories.
Outputs:
mirror_configured: Whether mirrors were configured successfullypackages_installed: List of successfully installed packagesubuntu_codename: Detected Ubuntu codename
Authenticate with Google Cloud using Workload Identity Federation with optional JWT debugging.
Usage:
- uses: zondax/gcp-wif-auth@v1
with:
workload_identity_provider: ${{ vars.PULUMI_DEPLOY_WIF_PROVIDER }}
project_id: ${{ vars.PULUMI_GCP_PROJECT_ID }}
log_jwt_info: trueInputs:
workload_identity_provider: Workload Identity Provider resource name (required)project_id: GCP Project IDservice_account: Service account email to impersonateaudience: Audience for the OIDC tokensetup_gcloud: Install and configure gcloud SDK (default: true)gcloud_version: Version of gcloud SDK to install (default: latest)gcloud_components: Additional gcloud components to install (comma-separated)log_jwt_info: Log JWT token information for debugging (default: true)verify_authentication: Verify authentication by running gcloud commands (default: true)export_credentials: Export credentials to environment (default: true)
Outputs:
credentials_path: Path to the generated credentials fileaccess_token: Access token for authenticated requestsproject_id: GCP Project ID
Three composite actions that sign release artifacts using GCP Cloud KMS keys, one per OS. They pair with gcp-wif-auth (which gained two new inputs to support the Windows Authenticode path; see gcp-wif-auth updates below).
Produce an armored OpenPGP detached signature (.asc) for any file using kunobi-pgp-kms backed by a GCP KMS signing key.
Runner: ubuntu-* (GitHub-hosted or self-hosted).
Usage:
- uses: zondax/sign-linux-binary@v1
with:
target-path: dist/myapp-linux-amd64.tar.gz
workload-identity-provider: ${{ vars.PGP_SIGN_WIF_PROVIDER }}
gcp-project-id: ${{ vars.PGP_SIGN_GCP_PROJECT_ID }}
kms-key: ${{ vars.PGP_SIGN_KMS_KEY_VERSION }}
cert-base64: ${{ secrets.PGP_CERT_BASE64 }}
signer-token: ${{ secrets.KUNOBI_SIGNER_TOKEN }}Inputs:
| Name | Required | Default | Description |
|---|---|---|---|
target-path |
yes | β | File to sign (e.g. a .tar.gz archive) |
workload-identity-provider |
yes | β | WIF provider (vars.PGP_SIGN_WIF_PROVIDER) |
gcp-project-id |
yes | β | GCP project (vars.PGP_SIGN_GCP_PROJECT_ID) |
service-account |
no | '' |
SA to impersonate; empty = direct principal-set |
signer-token |
yes | β | Token with read access on the private kunobi-ninja/kunobi-pgp-kms release |
kms-key |
yes | β | KMS key version path (vars.PGP_SIGN_KMS_KEY_VERSION) |
cert-base64 |
yes | β | Base64-encoded OpenPGP public cert (secrets.PGP_CERT_BASE64) |
signer-version |
no | latest |
kunobi-pgp-kms tag to install |
Outputs:
signature-path: path to the generated.ascfilecert-fingerprint: OpenPGP V4 key fingerprint
Runner prerequisites: gpg2 (pre-installed on ubuntu runners); mise is bootstrapped automatically if absent.
Authenticode-sign a Windows PE binary (.exe, x64 or arm64) using jsign against a GCP Cloud KMS key. Runs on the Linux runner where Windows targets are cross-built (cargo-xwin) β jsign is cross-platform and signs the PE regardless of where it was produced. The caller must obtain a GCP access token first via gcp-wif-auth with token_format: access_token.
Runner: Linux (same runner that cross-builds the -pc-windows-msvc target).
Usage:
- uses: zondax/gcp-wif-auth@v1
id: auth
with:
workload_identity_provider: ${{ vars.CODESIGN_WIF_PROVIDER }}
token_format: access_token
create_credentials_file: 'false'
- uses: zondax/sign-windows-binary@v1
with:
binary-path: dist/myapp.exe
gcp-access-token: ${{ steps.auth.outputs.access_token }}
kms-keyring: ${{ vars.CODESIGN_KMS_KEYRING }}
kms-key-alias: ${{ vars.CODESIGN_KMS_KEY_ALIAS }}
cert-chain: ${{ secrets.CODESIGN_CERT_CHAIN }}Inputs:
| Name | Required | Default | Description |
|---|---|---|---|
binary-path |
yes | β | Path to the .exe to sign |
gcp-access-token |
yes | β | GCP access token (from gcp-wif-auth access_token output) |
kms-keyring |
yes | β | KMS keyring (vars.CODESIGN_KMS_KEYRING) |
kms-key-alias |
yes | β | KMS key alias (vars.CODESIGN_KMS_KEY_ALIAS) |
cert-chain |
yes | β | PKCS7 EV cert chain PEM (secrets.CODESIGN_CERT_CHAIN) |
jsign-version |
no | 7.4 |
jsign version to download |
jsign-sha256 |
no | '' |
Expected SHA-256 of the jsign jar (pin; empty disables check β not recommended) |
tsa-url |
no | http://ts.ssl.com |
RFC3161 timestamp authority URL |
Outputs:
os-code-signature: compact JSON metadata ({"type":"authenticode","signer":"..."})
Runner prerequisites: runs on the Linux cross-build runner; a headless JRE is installed via apt-get if missing (no manual provisioning). jq is NOT required β the action builds its JSON output without it.
Codesign a bare Mach-O binary with rcodesign (reads the .p12 directly, avoiding the Security.framework bug on persistent self-hosted runners) and optionally submit for notarization via xcrun notarytool. The Apple credentials are fetched keyless from GCP Secret Manager via Workload Identity Federation β there are no Apple GitHub secrets. The action authenticates with the same CODESIGN_* identity used for Windows.
Runner: self-hosted macOS ARM64 (e.g. an Apple Silicon self-hosted runner).
Usage:
- uses: zondax/sign-macos-binary@v1
with:
binary-path: dist/myapp-darwin-arm64
workload-identity-provider: ${{ vars.CODESIGN_WIF_PROVIDER }}
gcp-project: ${{ vars.CODESIGN_GCP_PROJECT }} # e.g. zondax-code-signing
service-account: ${{ vars.CODESIGN_SERVICE_ACCOUNT }} # codesign@β¦; empty = direct WIF
notarize: 'true'Inputs:
| Name | Required | Default | Description |
|---|---|---|---|
binary-path |
yes | β | Mach-O file to sign |
workload-identity-provider |
yes | β | WIF provider (vars.CODESIGN_WIF_PROVIDER) |
gcp-project |
yes | β | GCP project holding the Apple secrets (vars.CODESIGN_GCP_PROJECT) |
service-account |
no | '' |
SA to impersonate (vars.CODESIGN_SERVICE_ACCOUNT); empty = direct principal-set WIF |
notarize |
no | false |
Submit for notarization after signing (true/false) |
certificate-secret |
no | apple-certificate-p12 |
Secret Manager id: base64 Developer ID .p12 |
certificate-password-secret |
no | apple-certificate-password |
Secret Manager id: .p12 password |
notary-key-secret |
no | apple-asc-api-key-p8 |
Secret Manager id: base64 ASC .p8 (notarize only) |
api-issuer-secret |
no | apple-asc-api-issuer |
Secret Manager id: ASC issuer id (notarize only) |
api-key-id-secret |
no | apple-asc-api-key-id |
Secret Manager id: ASC key id (notarize only) |
rcodesign-version |
no | 0.27.0 |
apple-codesign release tag |
rcodesign-sha256 |
no | '' |
Expected SHA-256 of the rcodesign tarball (pin; empty disables check β not recommended) |
Outputs:
os-code-signature: compact JSON metadata ({"type":"apple-codesigned"}or{"type":"apple-notarized","submissionId":"..."})
Runner prerequisites: xcrun (Xcode Command Line Tools), zip, and jq must be available. rcodesign is downloaded automatically. The runner needs OIDC (id-token: write) so the action can fetch the Apple creds from Secret Manager; no gcloud install is needed (the fetch uses google-github-actions/get-secretmanager-secrets).
gcp-wif-auth gained two new inputs to support token-only flows (used by the Windows Authenticode path):
| New input | Required | Default | Description |
|---|---|---|---|
token_format |
no | '' |
Token format to request from google-github-actions/auth ('', access_token, or id_token). Set to access_token to populate the access_token output β required by sign-windows-binary. |
create_credentials_file |
no | 'true' |
Whether auth writes an ADC credentials file. Pass 'false' for token-only flows (e.g. Windows Authenticode) where no ADC file is needed. |
- β Comprehensive Testing: Automated CI/CD with matrix testing across multiple environments
- β Security First: CodeQL analysis, secret scanning, dependency vulnerability checks
- β Performance Optimized: Swiss mirror optimization, fast-path/slow-path execution
- β Semantic Versioning: Automated releases with conventional commits
- β Monitoring: Performance benchmarking and health checks
- β Documentation: Comprehensive docs with troubleshooting guides
All actions are optimized for Zondax's Swiss infrastructure:
- π¨π Init7 Primary Mirror: Ultra-fast package downloads in Switzerland
- π« ETH Zurich Fallback: Academic network reliability
- π Global CDN Fallbacks: Worldwide availability
name: Zondax Enterprise CI/CD
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
setup:
runs-on: ubuntu-latest
outputs:
node-version: ${{ steps.setup.outputs.node-version }}
package-manager: ${{ steps.setup.outputs.pm }}
steps:
- name: Enterprise Checkout
uses: zondax/checkout-with-app@v1
with:
github_app_auth: true
github_app_repos: |
zondax/private-repo-1
zondax/private-repo-2
app_id: ${{ secrets.ZONDAX_APP_ID }}
app_pem: ${{ secrets.ZONDAX_APP_PEM }}
checkout_submodules: true
- name: Setup Development Environment
id: setup
uses: zondax/setup-node-env@v1
with:
node_version: '20'
package_manager: 'pnpm'
cache_dependencies: true
autoinit_env: true
- name: Install System Dependencies
uses: zondax/setup-ubuntu-packages@v1
with:
packages: |
build-essential
cmake
pkg-config
libssl-dev
libudev-dev
extra_packages: "jq tree htop"
enable_mirrors: true
security:
runs-on: ubuntu-latest
needs: setup
steps:
- name: Check Repository Health
uses: zondax/check-large-files@v1
with:
max_size: "50MB"
fail_on_large_files: true
deploy:
runs-on: ubuntu-latest
needs: [setup, security]
if: github.ref == 'refs/heads/main'
steps:
- name: Authenticate with GCP
uses: zondax/gcp-wif-auth@v1
with:
workload_identity_provider: ${{ vars.GCP_WIF_PROVIDER }}
project_id: ${{ vars.GCP_PROJECT_ID }}
service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}
log_jwt_info: false# Clone and setup development environment
git clone https://github.com/zondax/zondax-actions.git
cd zondax-actions
# Run automated setup
./scripts/dev-setup.sh
# Validate your changes
./scripts/validate-actions.sh
./scripts/security-check.sh
./scripts/test-all.sh- Read CONTRIBUTING.md for detailed guidelines
- Follow security best practices - all PRs are security scanned
- Add comprehensive tests - 100% test coverage required
- Update documentation - include usage examples
- Use conventional commits - enables automatic releases
# Validate all actions
./scripts/validate-actions.sh
# Run security checks
./scripts/security-check.sh
# Check for large files
./scripts/check-large-files.sh
# Run comprehensive tests
./scripts/test-all.sh- β‘ Average execution time: < 2 minutes for typical workflows
- π Swiss mirror performance: ~10x faster than default mirrors
- π Cache hit ratio: > 90% for dependencies
- π Success rate: > 99.5% across all actions
All actions include built-in monitoring:
- Performance benchmarking in CI/CD
- Error tracking and reporting
- Usage analytics (anonymous)
- Health checks and alerts
- π‘οΈ CodeQL Analysis: Automated security scanning
- π Secret Scanning: TruffleHog integration
- π¦ Dependency Scanning: Trivy vulnerability detection
- π Shell Security: ShellCheck and custom rules
- π·οΈ Supply Chain: Action dependency verification
- β SOC 2 Compatible: Audit trail and access controls
- β GDPR Compliant: No personal data collection
- β Enterprise Ready: Supports corporate proxies and air-gapped environments
- Major versions (v1, v2): Breaking changes, manual upgrade required
- Minor versions (v1.1.0): New features, backward compatible
- Patch versions (v1.1.1): Bug fixes, security updates
# β
Recommended: Use major version for automatic updates
- uses: zondax/action-name@v1
# β
Conservative: Pin to specific version
- uses: zondax/action-name@v1.2.3
# β Not recommended: Use main branch
- uses: zondax/action-name@main- π Documentation: Comprehensive guides for each action
- π Bug Reports: Open an issue
- π‘ Feature Requests: Discussion forum
- π Security Issues: security@zondax.ch
| Issue | Solution |
|---|---|
| Slow package installation | Enable mirrors with enable_mirrors: true |
| Authentication failures | Verify GitHub App permissions |
| Large file warnings | Use Git LFS or add to .gitignore |
| Node.js version conflicts | Pin version with node_version: 'X.Y.Z' |
# Enable verbose logging for debugging
- uses: zondax/setup-ubuntu-packages@v1
with:
packages: "build-essential"
enable_mirrors: true
verbose: true # π Enables detailed loggingApache License 2.0 - See LICENSE for details.