Reusable eirctl task configurations - enabling streamlined CI/CD workflows across Azure DevOps and GitHub Actions pipelines.
This repository provides task definitions that can be imported into your eirctl task runner. These configurations cover common Platform Engineering operations:
- Infrastructure as Code - Terraform formatting, validation, planning, and deployment
- Security and Quality - Static analysis with Checkov, PSScriptAnalyzer, YAML linting
- Pipeline Management - Azure DevOps pipeline retention and build numbering
- Git Operations - Automated tagging and GitHub releases
- Documentation - AsciiDoc to Markdown conversion and documentation builds
- Module Packaging - Terraform module build, copy, and zip packaging
Tasks run inside containerised execution contexts using Ensono Independent Runner (EIR) Docker images. Several tasks invoke PowerShell functions provided by the EIR containers (Invoke-Terraform, Invoke-YamlLint, Import-TerraformOutputsToAdoVariableGroup, Update-BuildNumber, Publish-GitHubRelease, Build-Documentation) rather than calling CLI tools directly.
- eirctl installed (v0.9.11+)
- Docker (for containerised task execution)
- Azure CLI credentials (for Azure-related tasks)
Import configurations directly from this repository into your eirctl.yaml file:
# yaml-language-server: $schema=https://raw.githubusercontent.com/Ensono/eirctl/refs/heads/main/schemas/schema_v1.json
import:
- https://raw.githubusercontent.com/Ensono/stacks-eirctl-configurations/main/shared/contexts/eirctl.yaml
- https://raw.githubusercontent.com/Ensono/stacks-eirctl-configurations/main/shared/infra/terraform.yaml
- https://raw.githubusercontent.com/Ensono/stacks-eirctl-configurations/main/shared/security/eirctl.yaml
watchers:
lint:
watch: ["*.yml"]
events: [create, write]
task: lint:yaml
terraform:
watch: ["*.tf", "*.tfvars"]
events: [create, write]
task: lint:terraform:format
pipelines:
lint:
- task: lint:yaml
- task: lint:terraform:format
depends_on: lint:yaml
- task: lint:terraform:validate
depends_on: lint:terraform:format
- task: lint:terraform:tflint
depends_on: lint:terraform:validate
scan:
- task: scan:terraform:checkov
tests:
- task: terraform:init:false
- task: terraform:tests
depends_on: terraform:init:false
infrastructure:plan:
- task: terraform:init
- task: terraform:plan
depends_on: terraform:init
infrastructure:apply:
- task: terraform:init
- task: terraform:apply
depends_on: terraform:initTip
Pin to a specific tag instead of main to prevent breaking changes.
Once imported, run tasks using eirctl:
# Linting
eirctl lint
# Security scanning
eirctl scan
# Terraform
eirctl tests
eirctl infrastructure:plan
eirctl infrastructure:applystacks-eirctl-configurations/
├── .github/
│ ├── copilot-instructions.md # AI assistant guidelines
│ └── pull_request_template.md
├── build/
│ └── ado/
│ ├── pipeline.yml # Azure DevOps CI pipeline
│ ├── templates/
│ │ └── setup.yml # Eirctl installation template
│ └── variables.yml # Pipeline variables
├── shared/ # All task configurations
│ ├── ado/
│ │ └── eirctl.yaml # Azure DevOps tasks
│ ├── contexts/
│ │ └── eirctl.yaml # Execution contexts (EIR Docker images)
│ ├── docs/
│ │ └── eirctl.yaml # Documentation tasks
│ ├── git/
│ │ └── eirctl.yaml # Git tagging tasks
│ ├── github/
│ │ └── eirctl.yaml # GitHub release tasks
│ ├── infra/
│ │ └── terraform.yaml # Terraform workflow tasks
│ └── security/
│ └── eirctl.yaml # Linting and scanning tasks
├── test/
│ └── eirctl.yaml # Combined config for CI validation
├── eirctl.yaml # Root config (imports for local dev)
├── yamllint.conf # YAML linting configuration
├── LICENSE
└── README.md
| Domain | Directory | Description |
|---|---|---|
| Azure DevOps | shared/ado/ |
Pipeline retention, build numbering |
| Contexts | shared/contexts/ |
EIR Docker execution contexts |
| Documentation | shared/docs/ |
AsciiDoc/Markdown generation |
| Git | shared/git/ |
Tagging and push operations |
| GitHub | shared/github/ |
Release publishing |
| Infrastructure | shared/infra/ |
Terraform lifecycle tasks |
| Security | shared/security/ |
Linting and static analysis |
| Validation | test/ |
Combined config for CI validation |
| Task | Description |
|---|---|
lint:terraform:format |
Perform Terraform format check (set TF_DEBUG=true for debug output) |
lint:terraform:validate |
Perform Terraform validate (set TF_DEBUG=true for debug output) |
lint:terraform:tflint |
Perform Terraform linting using TFLint (JUnit XML output) |
terraform:docs:asciidoc |
Generate Terraform module documentation into AsciiDoc format (requires TF_MODULE_NAME and docs/readme directory) |
terraform:docs:asciidoc:readme |
Copy the AsciiDoc-generated README to the module source directory (runs after docs:markdown) |
terraform:init |
Initialise Terraform (supports optional backend args, workspace, and TF_DEBUG) |
terraform:init:false |
Initialise Terraform with -backend=false |
terraform:tests |
Run Terraform tests with JUnit XML output (supports TF_TEST_FILTER) |
terraform:plan |
Terraform plan (set TF_DEBUG=true for debug output) |
terraform:apply |
Apply Terraform plan (set TF_DEBUG=true for debug output) |
terraform:destroy:plan |
Terraform destroy plan (set TF_DEBUG=true for debug output) |
terraform:destroy:apply |
Terraform destroy apply (set TF_DEBUG=true for debug output) |
terraform:build:clean |
Clean outputs folder |
terraform:build:copy |
Copy module files into outputs/module/ (supports nested and flat module layouts) |
terraform:build:package |
Create zip package for Terraform module (requires TF_MODULE_NAME) |
terraform:outputs:ado |
Add Terraform outputs to Azure DevOps variable group |
| Task | Description |
|---|---|
lint:yaml |
YAML linting using yamllint (set YAMLLINT_FAIL_ON_WARNINGS=true for strict mode) |
lint:powershell |
PSScriptAnalyzer on embedded PowerShell in eirctl YAML files (JUnit XML output) |
scan:terraform:checkov |
Terraform static code analysis using Checkov (JUnit XML output) |
| Task | Description |
|---|---|
docs:docbook |
Convert AsciiDoc documentation to Docbook for conversion to Markdown (requires ADOC_INDEX_FILE, docs/readme directory) |
docs:markdown |
Convert the Docbook README to Markdown (extracts title, adjusts headings, cleans up terraform-docs markers) |
docs:generate |
Build AsciiDoc documentation |
| Task | Description |
|---|---|
ado:build:number |
Update the build number in Azure DevOps |
ado:pipeline:retain |
Retain an Azure DevOps pipeline run (configurable via RETENTION_YEARS) |
| Task | Description |
|---|---|
git:tag |
Tag a commit and push to origin (ADO and GitHub) |
| Task | Description |
|---|---|
github:release |
Publish a GitHub Release |
| Variable | Used By | Description |
|---|---|---|
TF_FILE_LOCATION |
Terraform tasks | Path to Terraform files |
TF_DEBUG |
Terraform tasks | Set to true to enable debug output |
TF_BACKEND_INIT |
terraform:init |
Backend initialisation arguments |
TF_TEST_FILTER |
terraform:tests |
Optional filter for a specific test file |
TFLINT_CONFIG |
lint:terraform:tflint |
Path to TFLint configuration file |
ENVIRONMENT_NAME |
terraform:init |
Target environment/workspace name |
WORKSPACE_VARS_FILE |
terraform:plan, terraform:destroy:plan |
Optional tfvars file path |
ADO_ACCESS_TOKEN |
ADO tasks | Azure DevOps pipeline OAuth token ($(System.AccessToken)) |
ADO_ORGANISATION |
terraform:outputs:ado |
Azure DevOps organisation name |
ADO_VARIABLE_GROUP_NAME |
terraform:outputs:ado |
Variable group name for Terraform outputs |
ADO_VARIABLE_NAME_PREFIX |
terraform:outputs:ado |
Prefix for variable names in ADO |
RETENTION_YEARS |
ado:pipeline:retain |
Years to retain pipeline runs (default: 1) |
CHECKOV_VERSION |
scan:terraform:checkov |
Optional specific Checkov version |
TF_MODULE_NAME |
terraform:docs:asciidoc, terraform:build:package |
Module name used for docs/readme/<module> output folder and zip package filename |
ARTIFACTS_DIR |
github:release |
Release assets directory (default: outputs/assets) |
PUBLISH_RELEASE |
github:release |
Set to true to publish a release (default: true, handled by Publish-GitHubRelease) |
UPLOAD_ARTIFACTS |
github:release |
Set to false to skip artifact upload (default: true) |
PRERELEASE |
github:release |
Set to true to publish as a pre-release |
ADOC_INDEX_FILE |
docs:docbook |
Path to the AsciiDoc index file |
BUILDNUMBER |
docs:generate |
Build number for documentation generation |
YAMLLINT_FAIL_ON_WARNINGS |
lint:yaml |
Set to true to enable strict mode (default: false) |
PSSCRIPTANALYZER_EXCLUDE_RULES |
lint:powershell |
Comma-separated rule names to exclude |
PSSCRIPTANALYZER_PATH |
lint:powershell |
Override search directory (default: .) |
These are set automatically by the CI platform and do not need to be configured:
| Variable | Platform | Description |
|---|---|---|
SYSTEM_TEAMPROJECT |
ADO | Project name |
SYSTEM_COLLECTIONURI |
ADO | Organisation URI |
SYSTEM_DEFINITIONID |
ADO | Pipeline definition ID |
SYSTEM_ACCESSTOKEN |
ADO | Pipeline OAuth token |
BUILD_BUILDID |
ADO | Build run ID |
BUILD_BUILDNUMBER |
ADO | Build number |
BUILD_SOURCEVERSION |
ADO | Commit SHA |
BUILD_REQUESTEDFORID |
ADO | User who queued the build |
BUILD_REPOSITORY_NAME |
ADO | Repository full name |
BUILD_REPOSITORY_URI |
ADO | Repository URI |
GITHUB_SHA |
GitHub Actions | Commit SHA |
GITHUB_REPOSITORY |
GitHub Actions | Owner/repo name |
GITHUB_RUN_NUMBER |
GitHub Actions | Workflow run number |
GITHUB_TOKEN |
GitHub Actions | Automatic authentication token |
Tasks run inside Ensono Independent Runner (EIR) Docker containers defined in shared/contexts/eirctl.yaml:
| Context | Container | Purpose |
|---|---|---|
infra |
ensono/eir-infrastructure:1.2.45 |
Terraform, linting, scanning, PSScriptAnalyzer |
asciidoc |
ensono/eir-asciidoctor:1.2.45 |
Documentation generation |
powershell |
ensono/eir-foundation-powershell:1.2.45 |
ADO tasks, git operations, build/package |
EIR images provide PowerShell modules and CLI tools used by the tasks. Functions such as Invoke-Terraform, Invoke-YamlLint, Import-TerraformOutputsToAdoVariableGroup, Update-BuildNumber, Publish-GitHubRelease, and Build-Documentation are built into the containers.
Tasks that produce JUnit XML test results:
| Task | Output File |
|---|---|
lint:terraform:tflint |
test-results/tflint-results.xml |
lint:powershell |
test-results/psscriptanalyzer-results.xml |
terraform:tests |
test-results/terraform-test-results.xml |
scan:terraform:checkov |
test-results/checkov-results.xml |
Install the pre-commit hooks before making changes:
pre-commit install- Create or update a YAML file in the appropriate
shared/subdirectory - Follow the task naming convention:
category:subcategory:action(lowercase, colon-separated) - If a new file is added, add the file to
test/eirctl.yamlimports - Ensure all tasks have a
descriptionfield - Update this README with the new task
All changes are validated in CI:
# YAML linting
eirctl lint:yaml
# PowerShell static analysis
eirctl lint:powershell
# Verify all import paths resolve
# (checks that every file listed in test/eirctl.yaml imports exists on disk)
# Configuration validation
eirctl validate --config test/eirctl.yaml
# Verify tasks loaded
# (confirms at least one task was registered after validation)- YAML indentation: 2 spaces (enforced by yamllint)
- Task naming: Colon-separated namespaces in lowercase
- PowerShell: Use
$env:VARIABLE_NAMEfor environment variables - Descriptions: Required for all tasks; use pipe (
|) for multi-line - Error handling: Use
Write-Errorandexit 1for failures - EIR functions: Prefer EIR-provided functions over raw CLI invocations
- Test results: Write JUnit XML to
test-results/directory - Multi-platform: Use fallback pattern for ADO/GitHub variables (e.g.
BUILD_BUILDNUMBER/GITHUB_RUN_NUMBER)
The test/eirctl.yaml file imports all configuration files for combined validation. CI runs eirctl validate against this configuration on every pull request, alongside YAML linting and PSScriptAnalyzer checks.
- Fork the repository
- Create a feature branch
- Follow the coding standards above
- Add your file to
test/eirctl.yaml - Update this README with any new tasks
- Open a Pull Request
MIT License - see LICENSE for details.