Google Sign-In Required

Use your company Google account to access the BetterFleet private content.

Back to private home

BetterFleet Support Private
Skip to content
BetterFleet Dev Wiki
Terraform Plan Dry Runs
Initializing search
    bf-dev
    • Home
    • Product Capabilities
    • Process
    • Current Work
    • System Design
    • Software Reference
    • Operations
    bf-dev
    • Home
      • Overview
      • Manage
      • Overview
      • Product Engineering Workflow
      • Product Engineering Delivery
      • Product Engineering Workflow in Linear
        • GitLab Feature Flags
        • In-App Docs Authoring
        • Release Notes
      • Templates
      • Publishing
      • Workflow Companions
      • Overview
      • Active Artifacts
      • Backlog Artifacts
      • Archived Artifacts
      • Overview
      • Microgrid
      • OSCP
        • Challenge
        • Specification
        • Spec
        • Architecture
        • Overview
        • Script Runtime Model
        • Compose Profiles and Modes
        • Repo Topology
        • CI and Release Integration
        • Overview
        • Internal Application Diagrams
          • Overview
          • Web Model
          • Core Model
        • Service Interaction Flows
        • Data and State
          • Index
          • bf-manage-web
          • bf-manage-core
          • bf-manage-connect
          • bf-manage-sitepwrmon
          • bf-manage-incidents
          • bf-telematics
          • bf-depot-sim
          • bf-manage-roaming
          • bf-support-microsite
          • bf-digital-twin
          • bf-schedule-creator
        • Overview
        • Internal Application Diagrams
        • Migration and Flags
        • Simulation Request Lifecycle
          • Index
          • bf-bnl-ui
          • bf-bnl-settings
          • bf-bnl-schedule-analysis-compute
          • bf-route-modelling
          • bf-schedule-creator
          • bf-digital-twin
        • Overview
        • Secrets and Env Strategy
        • Vendors and Local Dependencies
        • ADRs
        • Service Matrix
        • Cloud Dependencies
        • Ports and URLs
      • Onboarding
      • Daily Operations Runbook
        • Overview
        • Staging Hotfix Release
        • Production Hotfix Release
        • Terraform Plan Dry Runs
          • 3AM Quick Guide
          • Purpose And When To Use It
          • Prerequisites And Permissions
          • Normal Procedure
          • Reference Screenshots
          • Decision Points And Exceptions
          • Validation And Evidence
          • Rollback And Recovery
          • Links To Service-Specific Details
      • Troubleshooting
      • Testing Guide
    • 3AM Quick Guide
    • Purpose And When To Use It
    • Prerequisites And Permissions
    • Normal Procedure
    • Reference Screenshots
    • Decision Points And Exceptions
    • Validation And Evidence
    • Rollback And Recovery
    • Links To Service-Specific Details

    Terraform Plan Dry Runs¶

    3AM Quick Guide¶

    • Use this only for IaC merge requests in repositories that already support the BF_PIPELINE_TYPE=dry-run path.
    • Get the required senior-engineer security review before exposing protected variables or runners to the merge request pipeline.
    • Temporarily enable MR access to protected variables and runners, and temporarily protect the MR source branch.
    • Trigger a new merge request pipeline with a commit message containing [dry-run].
    • In the pipeline, confirm the run is actually dry-run mode, review the Terraform plan artifacts, and make sure no deploy or apply jobs appear.
    • Remove the temporary protected access as soon as the review is complete. If deploy or apply jobs appear, stop immediately and disable access.

    Purpose And When To Use It¶

    This runbook explains how to validate infrastructure-as-code changes in a merge request by running Terraform plan through the merge request dry-run pipeline path before merge, without publishing releases, pushing Docker images, or running deploy or apply jobs.

    The shared trigger lives in bf-dev CI templates. Downstream repositories may implement different Terraform plan jobs, environments, regions, and evidence artifacts while still using the same BF_PIPELINE_TYPE=dry-run mechanism.

    Use this workflow when a merge request changes Terraform or other IaC that needs plan-level validation, and the plan requires protected variables or protected runners that are not normally available to merge request pipelines.

    This workflow exists so reviewers can inspect the Terraform plan for the MR before merge, without taking on the risks of running terraform plan locally and without needing to merge first just to see the plan output.

    Do not use this workflow for non-IaC changes, release pipelines, or any change that has not first been reviewed for CI and secret-handling safety.

    Prerequisites And Permissions¶

    Before using this workflow:

    • A senior engineer must review the merge request and confirm the pipeline or CI changes do not expose protected variables or runners unsafely.
    • That same senior engineer must temporarily change the repository CI/CD settings and branch protection while the dry run is being performed.
    • The target repository must actually implement the dry-run path. In the current BetterFleet setup, the shared trigger lives in ci-templates/Orchestration-Workflow.gitlab-ci.yml, while each repository owns its own dry-run-safe plan job rules and evidence outputs.
    • The dry-run pipeline is only triggered for merge request pipelines whose commit message contains [dry-run].

    In repositories that support this workflow:

    • BF_PIPELINE_TYPE becomes dry-run
    • DRY_RUN becomes true
    • any release metadata jobs needed by Terraform inputs should emit the expected variables without publishing a release
    • any build prerequisites should exit through their dry-run-safe path without building or pushing deployable artifacts
    • Terraform plan jobs should run or become available according to the target repository's established workflow
    • Terraform deploy and apply jobs should be blocked from appearing in the pipeline

    Normal Procedure¶

    1. Confirm the repository actually supports the dry-run path. For the BetterFleet mechanism, the shared trigger is defined in bf-dev/ci-templates/Orchestration-Workflow.gitlab-ci.yml. The target repository must also have its own dry-run-safe release, build, and Terraform plan job rules.
    2. Complete the security review before exposing protected variables to the MR pipeline.
    3. Temporarily enable protected access in GitLab for the target repository. Enable Allow merge request pipelines to access protected variables and runners.
    4. Temporarily add the MR source branch to the protected branches list.
    5. Trigger the dry-run pipeline with a commit message containing [dry-run].
    git commit --allow-empty --message "chore: trigger pipeline [dry-run]"
    git push
    
    1. Open the MR pipeline and confirm the dry-run trigger conditions are in effect. Confirm that the pipeline was created from the merge request after the [dry-run] commit, and confirm through job context, logs, or variable output that BF_PIPELINE_TYPE resolved to dry-run and DRY_RUN resolved to true where the target repository exposes those values.
    2. Wait for the dry-run prerequisites to complete. The exact prerequisite jobs vary by repository, but any release metadata and build-related steps should succeed through their dry-run-safe branches rather than publishing a release or pushing deployable artifacts.
    3. Review the Terraform plan jobs and artifacts. The exact plan jobs, environments, regions, and artifacts vary by repository. Review the target repository's configured plan jobs and use the relevant evidence artifacts for that repository, such as the GitLab Terraform report, plan.json, plan.cache, outputs.json, or equivalent outputs.
    4. Confirm no deploy or apply jobs are available in the pipeline before you treat the run as safe for review.
    5. Remove the temporary protected access as soon as the dry-run pipeline is no longer needed.

    Reference Screenshots¶

    These screenshots show the GitLab settings used during steps 3 and 4 of the normal procedure.

    Screenshot What It Shows File
    CI/CD variables settings The GitLab CI/CD settings area where Allow merge request pipelines to access protected variables and runners is enabled temporarily. terraform-plan-dry-run/cicd-variables.png
    Branch protection settings The branch protection page where the MR source branch is temporarily added to the protected branches list. terraform-plan-dry-run/branch-protection.png

    Decision Points And Exceptions¶

    • If the repository does not inherit the shared BFDev dry-run trigger or does not have downstream dry-run-safe Terraform plan jobs, stop and use a repository-specific process instead.
    • If the merge request does not change Terraform or other IaC that needs plan validation, do not use this workflow.
    • If the merge request changes CI definitions, pipeline scripts, Terraform job wiring, or secrets usage, treat that as a higher-risk run and require an explicit security review before enabling protected access.
    • If the target repository already has an established safe way to expose MR plan output without temporarily enabling protected access, use that repository-specific workflow instead.
    • If the [dry-run] trigger commit is present but the pipeline does not behave like the dry-run path, or if BF_PIPELINE_TYPE is not dry-run where that value is visible, stop and inspect the trigger conditions before trusting the result.
    • If any deploy or apply job appears in the pipeline, stop immediately, disable protected access, and treat the configuration as unsafe until reviewed.
    • If the target repository runs plan jobs automatically once prerequisites finish, review all relevant jobs or record the subset you intentionally checked.
    • If the target repository exposes manual plan jobs, run only the approved subset and record exactly which environments and regions were reviewed.

    Validation And Evidence¶

    Treat a dry-run review as complete only when you can point to evidence for each of these checks:

    • The pipeline was triggered from the merge request by a commit containing [dry-run], and the observed job behavior matches the dry-run path.
    • BF_PIPELINE_TYPE=dry-run and DRY_RUN=true were confirmed where the target repository exposes those values in job context, logs, or variable output.
    • The prerequisite jobs completed through their dry-run-safe branches rather than publishing a release or pushing Docker images.
    • The relevant Terraform plan jobs completed and produced reviewable artifacts or GitLab Terraform reports.
    • The reviewed plan output corresponds to the IaC changes in the merge request and was available before merging the branch.
    • No deploy or apply jobs were available in the pipeline.
    • The merge request or review note records which plan jobs were checked and any follow-up action or decision that came from the output.
    • The temporary protected access changes were removed after the review.

    Rollback And Recovery¶

    After the dry-run pipeline completes:

    • disable Allow merge request pipelines to access protected variables and runners
    • remove the MR source branch from the protected branches list
    • leave a short note in the MR if the dry-run output informed a decision

    If the dry-run pipeline exposes unexpected jobs or behavior:

    • cancel the pipeline if it is still running
    • disable protected MR access immediately
    • remove the MR source branch from protected branches
    • capture the pipeline link and the unexpected job names in the merge request
    • stop using this workflow until the CI rules are reviewed and corrected

    Links To Service-Specific Details¶

    • Shared trigger and workflow context: CI and Release Integration
    • Current shared trigger implementation: ci-templates/Orchestration-Workflow.gitlab-ci.yml
    • Current dry-run release metadata implementation: ci-templates/Semantic-Release.gitlab-ci.yml
    • Target repository Terraform-plan implementation: the target repository's .gitlab-ci.yml and included CI templates
    • Target repository runbooks and service docs: use the target repository's own docs for plan job names, environments, regions, approval rules, and evidence expectations
    Made with Material for MkDocs