Running Locally
Relevant source files
The following files were used as context for generating this wiki page:The Infrastructure as Code Recertification Engine (ICE) is a command-line tool designed to automate the recertification of IaC repositories. It operates by scanning files, checking their last modification dates against configured policies, and creating pull requests for items that require review. Running the engine locally is essential for development, testing configurations, and performing manual or ad-hoc recertification runs.
The primary command for executing the process is ice run. This command orchestrates the entire workflow, from configuration loading to pull request creation. Local execution relies on a configuration file and environment variables for authentication. A dry-run mode is available to simulate the process without making any changes to the target repository.
Sources: iac-recert-engine/cmd/ice/root.go:11-15, iac-recert-engine/cmd/ice/run.go:16-18
Execution Flow
When ice run is executed, it initiates a sequence of steps managed by the core Engine. The process is configuration-driven and modular, with distinct components responsible for each phase of the operation.
The diagram below illustrates the high-level execution flow of the ice run command.
This flow shows the progression from configuration loading to the final step of creating a pull request or logging the action in a dry run.
Sources: iac-recert-engine/cmd/ice/run.go:19-48, iac-recert-engine/internal/engine/engine.go:82-140
Engine Components
The core Engine struct orchestrates several specialized components to perform the recertification task.
The following sequence diagram shows the interactions between the Engine and its main components during a run.
The key components initialized and used by the engine are:
| Component | Description | Source File |
|---|---|---|
provider.GitProvider | An interface for Git operations (e.g., GitHub, GitLab) like creating branches, commits, and PRs. | internal/engine/engine.go:37-40 |
scan.Scanner | Clones the target repository and scans for files matching the configured patterns. | internal/engine/engine.go:43-44 |
scan.HistoryAnalyzer | Enriches file information by fetching the last modification date and commit details from the Git provider. | internal/engine/engine.go:45 |
scan.Checker | Compares the age of each file against its pattern's recertification_days to determine if it needs recertification. | internal/engine/engine.go:46 |
strategy.Strategy | Groups files that need recertification based on the configured pr_strategy (e.g., per_pattern, single_pr). | internal/engine/engine.go:48-52 |
assign.Resolver | Determines the assignees and reviewers for a pull request based on the assignment strategy. | internal/engine/engine.go:59 |
pr.Generator | Generates the title and description for a pull request based on the pr_template configuration. | internal/engine/engine.go:60 |
Sources: iac-recert-engine/internal/engine/engine.go:25-67
Configuration
Local execution is controlled via a YAML configuration file. The engine looks for this file based on the --config flag, the ICE_CONFIG_PATH environment variable, or in default locations like $HOME/.ice.yaml.
Sources: iac-recert-engine/cmd/ice/root.go:47-66
Key Configuration Options
The following table summarizes the main sections of the config.yaml file.
| Section | Description | Example |
|---|---|---|
repository | Specifies the target repository URL and its provider (github, azure, gitlab). | `url: "https://github.com/org/repo%22%60 |
auth | Defines the authentication method, typically an environment variable holding a personal access token. | token_env: "GITHUB_TOKEN" |
global | Global settings for the run, including dry_run mode and the default_base_branch. | dry_run: true |
patterns | An array of rules defining which files to scan, their recertification period, and an optional decorator to apply on update. | recertification_days: 180 |
pr_strategy | Determines how files are grouped into pull requests. Options include per_file, per_pattern, per_committer, single_pr. | type: "per_pattern" |
assignment | Defines the strategy for assigning PRs. Options include static, last_committer, and composite. | strategy: "last_committer" |
pr_template | A template for the title and body of the generated pull requests. Supports placeholders like {pattern_name}. | title: "Recertification: {pattern_name}" |
Sources: iac-recert-engine/example.config.yaml, iac-recert-engine/internal/config/types.go
Example Configuration
# example.config.yaml
version: "1.0"
repository:
url: "https://github.com/baldator/iac-recert-engine%22
provider: "github"
auth:
provider: "github"
token_env: "GITHUB_TOKEN"
global:
dry_run: false
default_base_branch: "main"
patterns:
- name: "terraform-prod"
paths:
- "terraform/prod/**/*.tf"
recertification_days: 180
enabled: true
decorator: "# Last Recertification: {timestamp}\n"
pr_strategy:
type: "per_pattern"
assignment:
strategy: "last_committer"
fallback_assignees:
- "devops-team"
pr_template:
title: "🔄 Recertification: {pattern_name}"
include_file_list: true
Sources: iac-recert-engine/example.config.yaml:4-53
Command-Line Usage
The ice binary provides the run subcommand to start the recertification process.
| Command / Flag | Description | Viper Binding |
|---|---|---|
ice run | The main command to run the recertification process. | N/A |
--config <path> | Specifies the path to the configuration file. | cfgFile variable |
--dry-run | Overrides the configuration to run in read-only mode without creating PRs. | global.dry_run |
--repo-url <url> | Overrides the repository URL specified in the configuration file. | repository.url |
Sources: iac-recert-engine/cmd/ice/run.go:15-18, 51-57, iac-recert-engine/cmd/ice/root.go:37-38
Local Testing with a File-based Repository
For development and testing, the engine can be pointed to a local Git repository using a file:// URL. This avoids network operations for cloning and allows for rapid, isolated testing of the engine's logic. The test suite for the engine uses this approach extensively.
To use this method:
- Initialize a local Git repository and commit some files.
- In your
config.yamlor via the--repo-urlflag, set the repository URL tofile:///path/to/your/local/repo. - Set
dry_run: trueto prevent the engine from attempting to create pull requests against a local-only repository, which would fail.
The following code snippet from the engine's test suite demonstrates how to set up a temporary local repository for a test run.
// iac-recert-engine/internal/engine/engine_test.go:167-198
// Create a temporary git repository for testing
tmpDir, err := os.MkdirTemp("", "engine-test-repo")
require.NoError(t, err)
defer os.RemoveAll(tmpDir)
// Create test files
testFile := filepath.Join(tmpDir, "main.tf")
err = os.WriteFile(testFile, []byte("resource \"aws_instance\" \"test\" {}"), 0644)
require.NoError(t, err)
// Initialize git repo
require.NoError(t, exec.Command("git", "init", tmpDir).Run())
// ... git add, git config, git commit ...
cfg := config.Config{
// ...
Repository: config.RepositoryConfig{
URL: "file://" + tmpDir, // Using a local file path
Provider: "github",
},
Global: config.GlobalConfig{
DryRun: true,
},
// ...
}
engine, err := NewEngine(cfg, logger)
require.NoError(t, err)
ctx := context.Background()
err = engine.Run(ctx)
// This should succeed with dry run
assert.NoError(t, err)
This pattern is invaluable for verifying configuration changes and developing new features without impacting a remote repository.
Sources: iac-recert-engine/internal/engine/engine_test.go:167-210