This guide helps developers and AI agents create new actions for the Flightcontrol actions repository. Actions are reusable workflow components that install tools and dependencies.
Actions provide a GitHub Actions-like way to install tools with specific versions. Users reference actions with uses: "action-name" and provide parameters via with. The system:
- Fetches the action file from GitHub (tries
.yaml,.yml, then.json) - Processes dependency templates, substituting
${{ inputs.param-name }}with provided values - Installs resolved dependencies using the runner's dependency manager
- Executes any additional instructions
Actions are defined in YAML or JSON format with this structure:
name: Action Name
description: Brief description of what this action does
inputs:
param-name:
description: Description of this parameter
required: false # or true
default: "default-value"
dependencyTemplates:
- name: dependency-name
# ... dependency configuration (see below)
instructions: [] # Optional additional commands to runname: Human-readable name of the actiondescription: Brief description of what the action doesinputs: Map of input parameters with their definitionsdependencyTemplates: Array of dependency configurations with template placeholdersinstructions: Array of additional commands to execute (usually empty for setup actions)
Each input parameter can have:
inputs:
version:
description: Tool version to install
required: false # Whether this parameter is mandatory
default: "1.0.0" # Default value if not providedUsers provide values via the with field:
{
"type": "uses",
"uses": "action-name",
"with": {
"version": "2.0.0"
}
}Use ${{ inputs.param-name }} syntax to reference input parameters in dependency configurations. The system substitutes these placeholders with actual values at runtime.
Example:
inputs:
node-version:
default: "20"
dependencyTemplates:
- name: node
package: nodejs${{ inputs.node-version }} # Becomes: nodejs20
version: ${{ inputs.node-version }} # Becomes: 20Template substitution works in all dependency fields: package, version, url, installScript.args, etc.
The runner supports multiple installation methods. Choose the appropriate method based on the tool:
Best for tools available in system package repositories.
dependencyTemplates:
- name: tool-name
package: package-name${{ inputs.version }}
version: ${{ inputs.version }}
checkBinary: binary-name
alternativePackages:
- alt-package-1
- alt-package-2Fields:
name: Unique identifier for the dependencypackage: Package name (with optional version suffix)version: Version to install (for verification)checkBinary: Binary to check if tool is already installedalternativePackages: Additional packages to install (e.g., dev tools, plugins)
Example - Node.js:
dependencyTemplates:
- name: node
package: nodejs${{ inputs.node-version }}
version: ${{ inputs.node-version }}
checkBinary: node
alternativePackages:
- nodejs${{ inputs.node-version }}-npmExample - Python:
dependencyTemplates:
- name: python
package: python${{ inputs.python-version }}
version: ${{ inputs.python-version }}
checkBinary: python${{ inputs.python-version }}
alternativePackages:
- python${{ inputs.python-version }}-dev
- python${{ inputs.python-version }}-venv
- python3-pipBest for tools distributed as precompiled binaries (Go, Terraform, etc.).
dependencyTemplates:
- name: tool-name
package: tool-name
installMethod: binary-download
checkBinary: binary-name
binaryDownload:
url: https://example.com/tool-${{ inputs.version }}-linux-$ARCH.tar.gz
archiveFormat: tar.gz # or zip
installPath: /usr/local/bin
architectureSpecific:
amd64: amd64
arm64: arm64
postInstall:
- export PATH=$PATH:/some/pathFields:
installMethod: Must bebinary-downloadbinaryDownload.url: Download URL with$ARCHplaceholder for architecturebinaryDownload.archiveFormat: Archive type (tar.gz,zip,tar, ornonefor raw binary)binaryDownload.installPath: Where to extract/install the binarybinaryDownload.architectureSpecific: Maps system architecture to URL architecture stringpostInstall: Commands to run after installation (e.g., PATH updates)
Architecture Mapping:
The $ARCH placeholder in URLs is replaced based on architectureSpecific:
- System
amd64→ URL containsamd64(if mapped toamd64) - System
arm64→ URL containsarm64(if mapped toarm64)
Example - Terraform:
dependencyTemplates:
- name: terraform
package: terraform
installMethod: binary-download
checkBinary: terraform
binaryDownload:
url: https://releases.hashicorp.com/terraform/${{ inputs.terraform-version }}/terraform_${{ inputs.terraform-version }}_linux_$ARCH.zip
archiveFormat: zip
installPath: /usr/local/bin
architectureSpecific:
amd64: amd64
arm64: arm64Example - Go:
dependencyTemplates:
- name: go
package: golang
installMethod: binary-download
checkBinary: go
binaryDownload:
url: https://go.dev/dl/go${{ inputs.go-version }}.linux-$ARCH.tar.gz
archiveFormat: tar.gz
installPath: /usr/local
architectureSpecific:
amd64: amd64
arm64: arm64
postInstall:
- export PATH=$PATH:/usr/local/go/binBest for tools with custom installation scripts (Google Cloud SDK, rustup, etc.).
dependencyTemplates:
- name: tool-name
package: tool-name
installMethod: install-script
checkBinary: binary-name
installScript:
url: https://install.example.com
args: --version=${{ inputs.version }} --install-dir=/usr/local
postInstall:
- export PATH=$PATH:/some/pathFields:
installMethod: Must beinstall-scriptinstallScript.url: URL of the installation scriptinstallScript.args: Arguments to pass to the script (supports templates)postInstall: Commands to run after installation
Example - Google Cloud SDK:
dependencyTemplates:
- name: gcloud
package: google-cloud-sdk
installMethod: install-script
checkBinary: gcloud
installScript:
url: https://sdk.cloud.google.com
args: --disable-prompts --install-dir=/usr/local
postInstall:
- export PATH=$PATH:/usr/local/google-cloud-sdk/bin
- gcloud config set core/disable_usage_reporting true
- gcloud config set component_manager/disable_update_check trueFor tools requiring custom installation logic, use preInstall and postInstall:
dependencyTemplates:
- name: tool-name
package: tool-name
checkBinary: binary-name
preInstall:
- curl -fsSL https://example.com/install.sh | bash
postInstall:
- export PATH=$PATH:/opt/tool/bin
- tool initIf your action needs to run commands after dependency installation, add them to instructions:
instructions:
- type: command
command: tool --version
- type: command
command: tool configure --defaultMost setup actions should have empty instructions: [] since the dependency installation is usually sufficient.
- Package Manager: Node.js, Python, Ruby, system tools
- Binary Download: Go, Terraform, OpenTofu, compiled tools
- Install Script: Tools with official installers (gcloud, rustup)
Choose popular, stable versions as defaults:
inputs:
version:
default: "3.11" # Popular, LTS versionname: Setup Python
description: Install a specific version of Python with pip and venv support
inputs:
python-version:
description: Python version to install (e.g., 3.8, 3.9, 3.10, 3.11)Use alternativePackages for tools users typically need:
alternativePackages:
- python${{ inputs.python-version }}-dev # Development headers
- python${{ inputs.python-version }}-venv # Virtual environment support
- python3-pip # Package managerFor binary downloads, always map both AMD64 and ARM64:
architectureSpecific:
amd64: amd64 # or x86_64, depending on URL format
arm64: arm64 # or aarch64, depending on URL formatIf the tool installs to a non-standard location, add it to PATH:
postInstall:
- export PATH=$PATH:/usr/local/go/binSetup actions should focus on installing dependencies. Keep instructions: [] unless you need post-install configuration.
{
"instructions": [
{
"type": "uses",
"uses": "owner/repo/your-action@branch",
"with": {
"version": "1.0.0"
}
},
{
"type": "command",
"command": "your-tool --version"
}
]
}Test with multiple versions to ensure template substitution works:
{"version": "1.0.0"}
{"version": "2.0.0"}
{"version": "latest"}Test without providing any with parameters to verify defaults work.
If your action uses binary downloads, test on both AMD64 and ARM64 systems.
The runner automatically tries multiple file extensions when fetching actions:
action.yaml(tried first)action.yml(fallback)action.json(final fallback)
Recommendation: Use action.yaml for better readability.
name: string # Unique identifier
package: string # Package name (supports templates)
version: string # Version (supports templates)
checkBinary: string # Binary to check for existing installation
installMethod: string # "binary-download" | "install-script"
alternativePackages: []string # Additional packages to install
# For binary-download method:
binaryDownload:
url: string # Download URL (use $ARCH for architecture)
archiveFormat: string # "tar.gz" | "zip" | "tar" | "none"
installPath: string # Installation directory
architectureSpecific: # Architecture mapping
amd64: string
arm64: string
# For install-script method:
installScript:
url: string # Script URL
args: string # Script arguments (supports templates)
# Lifecycle hooks:
preInstall: []string # Commands before installation
postInstall: []string # Commands after installationSee the examples/actions/ directory for reference implementations:
node/- Package manager with version-specific packagespython/- Package manager with alternative packagesterraform/- Binary download with ZIP archivego/- Binary download with tar.gz and PATH updategcp/- Install script with post-install configurationruby/- Package manager with dev toolstofu/- Binary download from GitHub releases
When creating new actions:
- Create a directory under
flightcontrolhq/actions/with your action name - Add an
action.yamlfile following this guide's structure - Test the action with different versions and parameters
- Submit a pull request with your action and usage examples
- Check existing actions in this repository for patterns
- Review the runner documentation in
packages/runner/README.md - Open an issue if you have questions or find bugs