### Basic GitHub Actions Workflow for Terraform/OpenTofu Source: https://github.com/op5dev/tf-via-pr/blob/main/README.md This example demonstrates a basic GitHub Actions workflow to provision infrastructure using Terraform or OpenTofu. It includes checkout, setup, and the tf-via-pr action for planning or applying changes based on the event type. ```yaml on: pull_request: push: branches: [main] jobs: provision: runs-on: ubuntu-latest permissions: actions: read # Required to identify workflow run. checks: write # Required to add status summary. contents: read # Required to checkout repository. pull-requests: write # Required to add PR comment. steps: - uses: actions/checkout@v6 - uses: hashicorp/setup-terraform@v4 with: terraform_wrapper: false # Run plan by default, or apply on merge. - uses: op5dev/tf-via-pr@v13 with: working-directory: path/to/directory command: ${{ github.event_name == 'push' && 'apply' || 'plan' }} arg-lock: ${{ github.event_name == 'push' }} arg-backend-config: env/dev.tfbackend arg-var-file: env/dev.tfvars arg-workspace: dev-use1 plan-encrypt: ${{ secrets.PASSPHRASE }} ``` -------------------------------- ### Install Missing Tools on GitHub-hosted Runners Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Use this command to install OpenSSL on GitHub-hosted runners if it's missing and required by the action. ```bash # Add missing tools apt-get update && apt-get install -y openssl ``` -------------------------------- ### Identifier Output Format Example Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/outputs.md These examples show the format of the unique plan artifact name generated by the 'identifier' output. It combines the tool, PR number, and configuration hash, with an optional encrypted extension. ```string terraform-123-a1b2c3d4e5f6g7h8.tfplan tofu-0-x9y8z7w6v5u4t3s2.tfplan.encrypted ``` -------------------------------- ### Terraform Initialization Example Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/action-reference.md Executes `terraform init` or `tofu init` with backend and state arguments. The exit code is trapped on EXIT. ```bash terraform init tofu init ``` -------------------------------- ### Example Failure Log Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md An example of a failure log, showing an error message and its formatted output. ```text Error: Failed to parse inputs: invalid command "foo" ##[error]Error: Failed to parse inputs: invalid command "foo" ``` -------------------------------- ### Install Required Tools on Custom Runners Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Install essential tools like gh, jq, md5sum, unzip, and openssl in your custom runner's environment or workflow. ```yaml - name: Install tools run: | apt-get update apt-get install -y gh jq md5sum unzip openssl ``` -------------------------------- ### Local Build and Test Commands Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Commands for installing dependencies, building the TypeScript project locally, and verifying the output JavaScript file. ```bash bun install bun run build ``` ```bash file dist/index.js head -c 200 dist/index.js ``` -------------------------------- ### Principle of Least Privilege Example Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md Illustrates the principle of least privilege by showing the minimum necessary permissions versus overly broad permissions for a GitHub Actions workflow. ```yaml # ✓ Minimum permissions: contents: read pull-requests: write # ✗ Too broad permissions: contents: write # Unnecessary pull-requests: admin # Unnecessary ``` -------------------------------- ### Future Node.js Runner Configuration Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Example of how the Node.js entry point could be integrated into action.yml in the future, specifying the main and post-execution scripts. ```yaml runs: using: node24 main: dist/index.js post: dist/index.js # cleanup phase ``` -------------------------------- ### Terraform Plan Example Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/action-reference.md Executes `terraform plan` or `tofu plan` with the detailed-exitcode flag and outputs to `tfplan`. Exit code 2 (changes detected) is treated as success. ```bash terraform plan -out=tfplan tofu plan -out=tfplan ``` -------------------------------- ### Display Terraform Command with Arguments Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/outputs.md This example shows how to display the formatted command input, including arguments, for transparency in PR comments. Hidden arguments are removed, and shown arguments are appended. Available for 'plan', 'apply', and 'init' commands. ```text terraform plan -chdir=path -var=key1=value1 -backend-config=backend.tf ``` -------------------------------- ### Workflow Invocation (Composite Action) Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Example of how the composite action is invoked from workflow steps using a specific command. ```yaml - uses: op5dev/tf-via-pr@v13 with: command: plan ``` -------------------------------- ### Example Success Log Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md A typical log message indicating a successful execution of the TypeScript entry point. ```text tf-via-pr TypeScript entry point (scaffold). ``` -------------------------------- ### Terraform Format Check Example Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/action-reference.md Executes `terraform fmt` or `tofu fmt` with options like check, diff, list, recursive, and write. The exit code is trapped on EXIT. ```bash terraform fmt tofu fmt ``` -------------------------------- ### Strong Passphrase Example using GitHub Secret Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/encryption-decryption.md Demonstrates how to use a strong, randomly generated passphrase stored as a GitHub secret for plan encryption. Ensure the secret is configured in repository settings. ```yaml plan-encrypt: ${{ secrets.TF_PLAN_PASSPHRASE }} ``` -------------------------------- ### Log Outputs in Workflow Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/outputs.md This example demonstrates how to capture and log various outputs from the tf-via-pr action in a GitHub Actions workflow. It shows how to access outputs like exitcode, summary, and comment-id. ```yaml - id: tf-via-pr uses: op5dev/tf-via-pr@v13 with: command: plan - name: Log outputs run: | echo "Exit code: ${{ steps.tf-via-pr.outputs.exitcode }}" echo "Summary: ${{ steps.tf-via-pr.outputs.summary }}" echo "Comment ID: ${{ steps.tf-via-pr.outputs.comment-id }}" ``` -------------------------------- ### Terraform Validation Example Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/action-reference.md Executes `terraform validate` or `tofu validate` with optional test arguments. The exit code is trapped on EXIT. ```bash terraform validate tofu validate ``` -------------------------------- ### Basic Plan-Only Workflow Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/common-patterns.md This snippet demonstrates the simplest setup for running a Terraform plan on a pull request. It ensures that validation and formatting checks are performed before posting the plan summary and diff as a PR comment. ```yaml name: Plan on: pull_request: jobs: plan: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v6 - uses: hashicorp/setup-terraform@v4 with: terraform_wrapper: false - uses: op5dev/tf-via-pr@v13 with: command: plan validate: true format: true ``` -------------------------------- ### Add Permissions to Workflow Level Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Example of setting default permissions for all jobs at the workflow level. ```yaml permissions: actions: read checks: write contents: read pull-requests: write jobs: terraform: runs-on: ubuntu-latest ``` -------------------------------- ### Workflow Invocation (Node.js Action - Future) Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Example of how the action would be invoked if it were a Node.js action, running the compiled JavaScript entry point. ```yaml - uses: op5dev/tf-via-pr@v14 # Would run dist/index.js as Node.js action # Currently runs action.yml composite steps ``` -------------------------------- ### Add Permissions to Job Level Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Example of specifying permissions directly within a job definition. ```yaml jobs: terraform: permissions: actions: read checks: write contents: read pull-requests: write ``` -------------------------------- ### Migration to Encrypted Terraform Plans Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/encryption-decryption.md This example shows how to update an existing GitHub Actions workflow to use encrypted Terraform plans by adding the `plan-encrypt` input with a reference to a GitHub secret. ```yaml # Before - uses: op5dev/tf-via-pr@v13 with: command: plan # After - uses: op5dev/tf-via-pr@v13 with: command: plan plan-encrypt: ${{ secrets.TF_PLAN_PASSPHRASE }} ``` -------------------------------- ### Conditional Steps Based on Exit Code Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/outputs.md This example shows how to implement conditional logic in a GitHub Actions workflow based on the exit code output of the tf-via-pr action. If the exit code is 2, it proceeds to download an artifact. ```yaml - id: tf uses: op5dev/tf-via-pr@v13 with: command: plan - name: Download artifact on changes if: "${{ steps.tf.outputs.exitcode == 2 }}" run: | gh api repos/${{ github.repository }}/actions/artifacts/${{ steps.tf.outputs.plan-id }}/zip -H "Accept: application/vnd.github+json" > plan.zip ``` -------------------------------- ### Check Identifier in Comment Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Example of an identifier format within a comment's body. ```markdown ``` -------------------------------- ### Pass Results to Subsequent Actions Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/outputs.md This example illustrates how to pass outputs from the tf-via-pr action to subsequent steps in a GitHub Actions workflow, specifically using the 'actions/github-script' action to log the summary and run URL. ```yaml - id: tf uses: op5dev/tf-via-pr@v13 with: command: apply - name: Post summary uses: actions/github-script@v7 with: script: | console.log("${{ steps.tf.outputs.summary }}") console.log("Run URL: ${{ steps.tf.outputs.run-url }}") ``` -------------------------------- ### Comment Body Structure Example Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/outputs.md This markdown structure shows the complete body of a PR comment, including command, diff, summary, and optional custom positions. It's used when a PR comment is created and the command is 'plan', 'apply', or 'init'. ```markdown ```markdown {pos-1} ```fish {command} ``` {pos-2} {diff} {pos-3}
{summary} {pos-4} By @{actor} at {timestamp} [view log]({url}) ```hcl {console output} ```
{pos-5} {pos-6} ``` ``` -------------------------------- ### Setup Checkov Action for Policy Validation Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md Integrates the Checkov action into a GitHub Actions workflow for policy validation and security scanning of Terraform code. ```yaml - uses: checkov/checkov-action@v1 ``` -------------------------------- ### Setup Terraform Linters Action Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md Integrates the TFLint action into a GitHub Actions workflow for linting Terraform code, including security-focused checks. ```yaml - uses: terraform-linters/setup-tflint@v4 ``` -------------------------------- ### Setup TFSEC Action for Security Scanning Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md Integrates the TFSEC action into a GitHub Actions workflow to perform security scanning on Terraform code. ```yaml - uses: aquasecurity/tfsec-action@v1 ``` -------------------------------- ### Set GitHub Repository Secret Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md Example command to set a GitHub repository secret using the GitHub CLI. This is a recommended practice for managing sensitive values like encryption passphrases. ```bash gh secret set TF_PLAN_PASSPHRASE -b "$(openssl rand -base64 32)" ``` -------------------------------- ### Extract Lines Starting with ' # ' Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/diff-generation.md Filters lines from a console output file that begin with two spaces followed by a hash and a space. This is the initial step in identifying resource change descriptions. ```bash grep '^ # ' tf.console.txt ``` -------------------------------- ### Recommended TF-via-PR Configuration Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/README.md This configuration includes common options for plan and apply, validation, formatting, encryption, and backend configuration. It also demonstrates conditional logic for setting the command based on the GitHub event. ```yaml - uses: hashicorp/setup-terraform@v4 with: terraform_wrapper: false - uses: op5dev/tf-via-pr@v13 with: command: ${{ github.event_name == 'push' && 'apply' || 'plan' }} validate: true format: true plan-encrypt: ${{ secrets.PASSPHRASE }} arg-lock: ${{ github.event_name == 'push' }} arg-backend-config: key=terraform.tfstate arg-var-file: env/dev.tfvars arg-workspace: dev ``` -------------------------------- ### Minimal TF-via-PR Configuration Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/README.md This snippet shows the most basic configuration for using the tf-via-pr action to perform a plan. ```yaml - uses: op5dev/tf-via-pr@v13 with: command: plan ``` -------------------------------- ### Use Static Matrix Strategy Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md YAML configuration for a static matrix strategy, avoiding dynamic resolution issues. ```yaml strategy: matrix: environment: [dev, staging, prod] ``` -------------------------------- ### Configure Terraform Provider Caching Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Cache Terraform providers to speed up subsequent runs. This example uses the actions/cache action to cache plugins. ```yaml - uses: actions/cache@v4 with: path: ~/.terraform/plugin-cache key: ${{ runner.os }}-plugins-${{ hashFiles('.terraform.lock.hcl') }} ``` -------------------------------- ### Enable Format Checking Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Enables Terraform/OpenTofu format checking by running 'terraform fmt' or 'tofu fmt' before plan/apply. ```yaml format: true ``` -------------------------------- ### Async Task Handling in TypeScript Entry Point Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Illustrates a potential future implementation for handling asynchronous tasks, including input parsing, command execution, and artifact handling. ```typescript async function run(): Promise { // Parse and validate inputs const inputs = parseInputs(process.env); // Build arguments const args = buildArgs(inputs); // Execute terraform command const result = await executeCommand(args); // Handle artifacts if (inputs.uploadPlan) { await uploadArtifact(result.planFile, inputs); } // Post comment if (inputs.commentPr) { await postComment(result, inputs); } // Set outputs setOutputs(result); } ``` -------------------------------- ### Logging with @actions/core Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Demonstrates how to use @actions/core for different logging levels within the action. ```typescript core.info("message") // Info level core.warning("message") // Warning level core.error("message") // Error level core.setFailed("message") // Failure with exit ``` -------------------------------- ### Count Non-Comment Lines in Diff Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/diff-generation.md Counts the number of lines in the generated diff file that do not start with '# '. This count represents the actual number of resource changes. ```bash diff_count=$({ grep --invert-match '^# ' tf.diff.txt || true; } | wc --lines) ``` -------------------------------- ### Specify Existing Plan File Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Provides the path to an existing plan file, used for applying a pre-generated plan. ```yaml plan-file: path/to/file.tfplan ``` -------------------------------- ### Build Node.js Entry Point Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Builds the TypeScript entry point file into a minified CommonJS JavaScript file for Node.js runtime. ```bash bun build src/main.ts --target=node --format=cjs --minify --sourcemap=none --outfile=dist/index.js ``` -------------------------------- ### Get Artifact ID via GitHub CLI Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/encryption-decryption.md Retrieves the ID of a specific artifact by its name using the GitHub CLI API. This ID is needed to download the artifact. ```bash gh api repos/${{ github.repository }}/actions/artifacts \ --field name="terraform-123-abc.tfplan.encrypted" \ --jq '.artifacts[0].id' ``` -------------------------------- ### Multi-Environment Matrix Workflow Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/common-patterns.md This workflow deploys to multiple environments (dev, staging, prod) using a GitHub Actions matrix strategy. It ensures sequential execution for safety, with each environment receiving a separate PR comment and plan file. ```yaml name: Multi-Env Deploy on: pull_request: push: branches: [main] jobs: terraform: strategy: matrix: environment: [dev, staging, prod] max-parallel: 1 # Sequential for prod safety runs-on: ubuntu-latest environment: ${{ matrix.environment }} permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v6 - uses: hashicorp/setup-terraform@v4 with: terraform_wrapper: false - uses: op5dev/tf-via-pr@v13 with: command: ${{ github.event_name == 'push' && 'apply' || 'plan' }} working-directory: envs/${{ matrix.environment }} arg-workspace: ${{ matrix.environment }} arg-var-file: ${{ matrix.environment }}.tfvars ``` -------------------------------- ### Manual Approval Workflow for Terraform Apply Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md Sets up a manual approval step in a GitHub Actions workflow before applying Terraform changes to a production environment. Ensures human oversight. ```yaml jobs: plan: if: github.event_name == 'pull_request' # ... runs plan ... approval: if: github.event_name == 'pull_request' needs: plan environment: production # Requires manual approval runs-on: ubuntu-latest steps: - run: echo "Approval granted" apply: if: github.event_name == 'push' # ... runs apply ... ``` -------------------------------- ### Check Plan Output for Changes Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Command to inspect the plan output for indications of changes. ```bash terraform show tfplan | grep "# .*will be" ``` -------------------------------- ### Download Artifact via GitHub CLI Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/encryption-decryption.md Downloads a specific artifact as a zip file using its ID and the GitHub CLI API. The downloaded zip is then extracted. ```bash gh api repos/${{ github.repository }}/actions/artifacts/ARTIFACT_ID/zip > tfplan.zip unzip -d . tfplan.zip ``` -------------------------------- ### Set Provisioning Tool Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Defines the provisioning tool to be used, either 'terraform' or 'tofu'. ```yaml tool: terraform ``` -------------------------------- ### Decrypt Encrypted Plan Locally Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/encryption-decryption.md Downloads an artifact, unzips it, and then decrypts the plan file using OpenSSL. Ensure the passphrase matches the one used during encryption. ```bash # Download artifact gh api repos/${{ github.repository }}/actions/artifacts/ARTIFACT_ID/zip > tfplan.zip unzip tfplan.zip # Decrypt plan file openssl enc -d -aes-256-ctr -pbkdf2 -salt \ -in tfplan.encrypted \ -out tfplan.decrypted \ -pass pass:"" # View decrypted plan terraform show tfplan.decrypted ``` -------------------------------- ### Format Terraform Code Locally Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Apply consistent formatting to your Terraform code by running the `terraform fmt` command recursively. ```bash terraform fmt -recursive ``` -------------------------------- ### Show CLI Arguments Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Defines a comma-separated list of CLI arguments to explicitly show in the PR comment, even if not in the actual command. ```yaml show-args: workspace ``` -------------------------------- ### Enable Plan Parity Check Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Replaces the plan file if a newly generated plan matches a downloaded plan, preventing stale applies in merge queue scenarios. ```yaml plan-parity: true ``` -------------------------------- ### Cost Estimation with Tool Integration Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/common-patterns.md Integrate external cost estimation tools like Infracost by chaining them after the `plan` command. The results can then be posted to the PR comment. ```yaml name: Plan with Cost Estimate on: pull_request: jobs: terraform: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v6 - uses: hashicorp/setup-terraform@v4 with: terraform_wrapper: false - id: tf uses: op5dev/tf-via-pr@v13 with: command: plan - id: cost run: | # Example: Run Infracost echo "cost_summary=Monthly increase: ~\$500" >> $GITHUB_OUTPUT - uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: '**Cost Estimate**: ${{ steps.cost.outputs.cost_summary }}' }) ``` -------------------------------- ### List GitHub Artifacts by Name Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/github-api-integration.md Use this command to find plan file artifacts by their name. It filters artifacts based on the provided name and returns the artifact ID. ```bash gh api /repos/$GH_REPO/actions/artifacts \ --header "$GH_API" \ --method GET \ --field "name=$GH_IDENTIFIER_NAME" \ --jq '.artifacts[0].id' ``` -------------------------------- ### View Full Plan Output Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Command to display the complete output of a Terraform plan. ```bash terraform show tfplan ``` -------------------------------- ### Set Command to Plan Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Specifies the command to execute, such as 'plan' for generating an execution plan. ```yaml command: plan ``` -------------------------------- ### Enable GitHub CLI Debugging Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Environment variable to enable detailed API logging for GitHub CLI commands. ```bash export GH_DEBUG=api ``` -------------------------------- ### View Full Workflow Logs in GitHub Actions Tab Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Instructions for navigating the GitHub Actions tab to view detailed workflow and job logs. ```markdown 1. Go to Actions tab in GitHub 2. Click workflow run 3. Click job name 4. View "Run op5dev/tf-via-pr@v13" step 5. Expand step to see all output ``` -------------------------------- ### Run Action with GitHub CLI Debugging Enabled Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Workflow step configuration to enable GH_DEBUG for API logs. ```yaml - name: Run action with debug env: GH_DEBUG: api run: | # gh CLI calls will show detailed API logs ``` -------------------------------- ### Expand Comma-Separated 'backend-config' Argument Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Shows the expansion of comma-separated values for 'arg-backend-config' into individual flags. ```yaml arg-backend-config: backend.tf,config.tfbackend # Expands to: -backend-config=backend.tf -backend-config=config.tfbackend ``` -------------------------------- ### Download GitHub Artifact by ID Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/github-api-integration.md Download a specific artifact, typically a plan file, using its ID. The downloaded content is saved as a zip archive. ```bash gh api /repos/$GH_REPO/actions/artifacts/${artifact_id}/zip \ --header "$GH_API" \ --method GET > "$GH_IDENTIFIER_NAME.zip" ``` -------------------------------- ### Node.js Entry Point Scaffold Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md The main entry point for the action, serving as a top-level error boundary. It logs a placeholder message and catches any errors during execution. ```typescript import * as core from "@actions/core"; /** * Entry point for the Terraform/OpenTofu via PR action. * * Phase 0 (scaffold): this is an intentional placeholder that establishes the * `node` runtime entry point and the top-level error boundary. The action is * still driven by the composite `action.yml`; subsequent phases move logic into * dedicated modules (inputs, args, exec, github, artifact, crypto, comment) and * wire them in here. See the migration plan for phase boundaries. */ async function run(): Promise { core.info("tf-via-pr TypeScript entry point (scaffold)."); } run().catch((error: unknown) => { core.setFailed(error instanceof Error ? error.message : String(error)); }); ``` -------------------------------- ### Set Syntax Highlighting Based on Plan Outcome Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/diff-generation.md Determines the syntax highlighting for diff output based on the outcome of a previous step. Uses 'diff' for failure and 'hcl' otherwise. ```bash if [[ "${{ steps.format.outcome }}" == "failure" ]]; then syntax="diff" else syntax="hcl" fi ``` -------------------------------- ### GitOps with Label-Triggered Apply Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/common-patterns.md Automate Terraform apply operations based on a specific label being added to a pull request. This enables a lightweight approval process for deployments. ```yaml name: GitOps Apply on: pull_request: types: [labeled] jobs: apply: if: ${{ github.event.label.name == 'apply' }} runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v6 - uses: hashicorp/setup-terraform@v4 with: terraform_wrapper: false - uses: op5dev/tf-via-pr@v13 with: command: apply comment-pr: always tag-actor: always ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Sets environment variables for Terraform/OpenTofu execution, useful for authentication and configuration. ```yaml env: AWS_REGION: us-east-1 TF_VAR_environment: production ``` -------------------------------- ### Set Working Directory Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Specifies the path to the Terraform or OpenTofu code directory. ```yaml working-directory: path/to/directory ``` -------------------------------- ### Matrix Strategy for Multiple Environments Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/workflow-triggers.md Deploy to multiple environments by defining a matrix strategy. The action automatically handles matrix job ID detection with retry. ```yaml on: push: branches: [main] jobs: apply: strategy: matrix: environment: [dev, staging, prod] runs-on: ubuntu-latest permissions: pull-requests: write steps: - uses: actions/checkout@v6 - uses: op5dev/tf-via-pr@v13 with: command: apply working-directory: envs/${{ matrix.environment }} arg-var: environment=${{ matrix.environment }} ``` -------------------------------- ### Echo Plan Artifact URL Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/outputs.md Use this snippet to echo the URL for downloading the plan file artifact. This is available when the command is 'plan' and artifact upload is enabled. ```yaml echo "Download plan from: ${{ steps.tf-plan.outputs.plan-url }}" ``` -------------------------------- ### Display Terraform Command Output Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/outputs.md This snippet shows the complete console output from the last Terraform/OpenTofu command, formatted as a markdown code block with HCL syntax highlighting. Output is truncated to 42000 bytes. Available for 'plan', 'apply', and 'init' commands. ```hcl Plan: 1 to add, 0 to change, 1 to destroy. Outputs: instance_id = "i-1234567890abcdef0" ``` -------------------------------- ### Encrypt Plan File Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Provides a passphrase for encrypting the plan file using OpenSSL AES-256-CTR with PBKDF2 and salt. The passphrase must be consistent between plan and apply phases. ```yaml plan-encrypt: ${{ secrets.PASSPHRASE }} ``` -------------------------------- ### Verify Build Output Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Verifies that the build process has not introduced unintended changes to the output JavaScript file by checking for differences in the dist directory. ```bash git diff --exit-code --stat -- dist/ ``` -------------------------------- ### Drift Detection and Issue Creation Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/common-patterns.md This workflow runs a scheduled 'plan' with refresh-only enabled to detect configuration drift. If drift is detected (exitcode 2), it creates a GitHub issue to report it. ```yaml name: Drift Detection on: schedule: - cron: '0 8 * * *' jobs: refresh: runs-on: ubuntu-latest permissions: actions: read checks: write contents: read issues: write steps: - uses: actions/checkout@v6 - uses: hashicorp/setup-terraform@v4 with: terraform_wrapper: false - id: tf uses: op5dev/tf-via-pr@v13 with: command: plan arg-refresh-only: true pr-number: "0" - if: ${{ steps.tf.outputs.exitcode == 2 }} uses: actions/github-script@v7 with: script: | const drift = `${{ steps.tf.outputs.diff }}` const summary = `${{ steps.tf.outputs.summary }}` github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, title: 'Configuration drift detected', body: `Drift detected during scheduled refresh.\n\n${summary}\n\n${drift}`, labels: ['terraform', 'drift'] }) ``` -------------------------------- ### Troubleshooting Artifact Not Found Error Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/encryption-decryption.md This error occurs when the encrypted plan artifact cannot be located. Verify artifact retention policies, ensure consistent identifiers between plan and apply phases, and check if artifact upload is enabled. ```text Unable to locate plan file: terraform-123-abc.tfplan.encrypted. ``` -------------------------------- ### OpenSSL Encryption Command Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/encryption-decryption.md Encrypts a plan file using OpenSSL AES-256-CTR with PBKDF2 key derivation and a salt. The `-pass pass:""` option reads the passphrase directly. ```bash openssl enc -aes-256-ctr -pbkdf2 -salt \ -in tfplan \ -out tfplan.encrypted \ -pass pass:"" ``` -------------------------------- ### Enable Validation Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Enables Terraform/OpenTofu validation by running 'terraform validate' or 'tofu validate' before plan/apply. ```yaml validate: true ``` -------------------------------- ### Node.js Version Compatibility in package.json Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Specifies the required Node.js version range for the action, targeting Node.js 24 or later. ```json "engines": { "node": ">=24" } ``` -------------------------------- ### Activate Plan Encryption in Workflow Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/encryption-decryption.md Enable plan encryption by setting the `plan-encrypt` input to your passphrase secret. The plan file will be encrypted after generation and replaced in the artifact. ```yaml - uses: op5dev/tf-via-pr@v13 with: command: plan plan-encrypt: ${{ secrets.PASSPHRASE }} ``` -------------------------------- ### Variable-Driven Plan with Workflow Inputs Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/common-patterns.md This workflow allows dynamic execution of Terraform commands based on user-provided inputs for environment, command type, and parallelism. It uses workflow dispatch for manual triggering. ```yaml name: Dynamic Plan on: workflow_dispatch: inputs: environment: required: true type: choice options: [dev, staging, prod] command: required: true type: choice options: [plan, apply] parallelism: required: false default: 10 jobs: terraform: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v6 - uses: hashicorp/setup-terraform@v4 with: terraform_wrapper: false - uses: op5dev/tf-via-pr@v13 with: command: ${{ inputs.command }} working-directory: envs/${{ inputs.environment }} arg-workspace: ${{ inputs.environment }} arg-var-file: ${{ inputs.environment }}.tfvars arg-parallelism: ${{ inputs.parallelism }} pr-number: "0" ``` -------------------------------- ### Profile Terraform Plan Locally Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Measure the execution time of the 'terraform plan' command locally. This helps identify performance bottlenecks in Terraform commands. ```bash time terraform plan ``` -------------------------------- ### Filter Changes from Plan Output Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Using jq to filter and display resource changes from a JSON plan output. ```bash terraform show -json tfplan | jq '.resource_changes' ``` -------------------------------- ### Display Collapsible HTML Diff Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/outputs.md This snippet demonstrates the HTML-formatted collapsible diff section showing resource changes. It is generated when the plan or download step succeeds and a diff exists. The diff is expandable by default if 'expand-diff' input is true and truncated if it exceeds 24000 bytes. ```html
Diff of N changes. `diff + aws_instance.example will be created - aws_db_instance.legacy will be destroyed ! aws_s3_bucket.config will be updated ~ aws_security_group.web will be read … `
``` -------------------------------- ### Check Artifact Existence via GitHub API Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Use this command to verify if the plan artifact exists in your repository's GitHub Actions artifacts. ```bash gh api repos/$GITHUB_REPOSITORY/actions/artifacts \ --field name="terraform-123-abc.tfplan" ``` -------------------------------- ### Download Artifact Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/github-api-integration.md Download an artifact by its ID. This is used for retrieving plan files, whether encrypted or unencrypted, for subsequent apply operations. ```APIDOC ## GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/zip ### Description Download an artifact by its ID. This is used for retrieving plan files, whether encrypted or unencrypted, for subsequent apply operations. ### Method GET ### Endpoint /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/zip ### Response #### Success Response Binary ZIP archive containing plan file(s) ### Headers - `Accept: application/vnd.github+json` - `X-GitHub-Api-Version: 2022-11-28` ``` -------------------------------- ### Terraform Plan Parity Check Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/action-reference.md Compares a newly generated Terraform plan with a downloaded or supplied plan to detect configuration drift. It generates a new plan, shows both plans as JSON, filters non-no-op changes, and compares them using diff. ```bash terraform plan ... -out=tfplan.parity ``` ```bash terraform show -json ``` ```bash jq --sort-keys '[(.resource_changes? // [])[] | select(.change.actions != ["no-op"]) ]' ``` ```bash diff --brief ``` -------------------------------- ### Upload Plan File Artifact Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Enables uploading the plan file as a GitHub workflow artifact for later download during the apply phase. ```yaml upload-plan: true ``` -------------------------------- ### View GitHub Audit Log for Repository Events Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md Uses the GitHub CLI to view audit logs for a repository, allowing for tracking of events and changes. ```bash # View repository events gh audit-log ``` -------------------------------- ### Report Compliance Status to GitHub Summary Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md Log compliance check results to the GitHub step summary. This provides a quick overview of policy check outcomes within the workflow run. ```yaml - name: Report compliance run: | # Log compliance check results echo "Policy checks: PASSED" >> $GITHUB_STEP_SUMMARY ``` -------------------------------- ### Configure Encrypted Plan Passphrase Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Ensure the `plan-encrypt` passphrase is set identically in both the plan and apply phases of your workflow using GitHub secrets. ```yaml # Plan phase plan-encrypt: ${{ secrets.TF_PLAN_PASSPHRASE }} # Apply phase (must be identical) plan-encrypt: ${{ secrets.TF_PLAN_PASSPHRASE }} ``` -------------------------------- ### Check Artifact Size Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Verify the size of a Terraform plan artifact in bytes. This can help diagnose slow artifact download issues. ```bash gh api repos/$GITHUB_REPOSITORY/actions/artifacts \ --field name="terraform-123-abc.tfplan" \ --jq '.artifacts[0].size_in_bytes' ``` -------------------------------- ### Using GitHub Secrets for Sensitive Inputs Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md Demonstrates the secure way to handle sensitive inputs like encryption passphrases or database passwords by referencing GitHub secrets. Avoid hardcoding secrets directly in the workflow file. ```yaml # ✓ Good: Use secrets plan-encrypt: ${{ secrets.PASSPHRASE }} arg-var: db_password=${{ secrets.DB_PASSWORD }} # ✗ Bad: Hardcoded secrets plan-encrypt: "my-password-123" arg-var: db_password=secret123 ``` -------------------------------- ### Local Decryption of Encrypted Terraform Plan Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/encryption-decryption.md This script downloads an encrypted plan artifact from GitHub, decrypts it using a provided passphrase, and then verifies the decrypted plan. It's useful for local testing or manual apply steps. ```bash #!/bin/bash set -e # Download artifact artifact_id=$1 passphrase=$2 gh api repos/$GITHUB_REPOSITORY/actions/artifacts/$artifact_id/zip > tfplan.zip unzip -j tfplan.zip # Decrypt openssl enc -d -aes-256-ctr -pbkdf2 -salt \ -in tfplan.encrypted \ -out tfplan \ -pass pass:"$passphrase" # Verify terraform show tfplan # Clean up shred -vfz -n 3 tfplan.encrypted ``` -------------------------------- ### Secure Terraform Workflow with GitHub Actions Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/security-considerations.md This workflow demonstrates a hardened approach to managing Terraform with GitHub Actions. It includes steps for checkout, AWS credential configuration, linting, security scanning, and Terraform operations with encryption. ```yaml name: Secure Terraform on: pull_request: push: branches: [main] permissions: actions: read checks: write contents: read id-token: write pull-requests: write jobs: terraform: runs-on: ubuntu-latest environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }} steps: # Setup - uses: actions/checkout@v6 - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789:role/TerraformGitHubAction aws-region: us-east-1 # Security checks - uses: terraform-linters/setup-tflint@v4 - run: tflint --format compact - uses: aquasecurity/tfsec-action@v1 - uses: checkov/checkov-action@v1 with: directory: terraform/ # Terraform - uses: hashicorp/setup-terraform@v4 with: terraform_wrapper: false - uses: op5dev/tf-via-pr@v13 with: command: ${{ github.event_name == 'push' && 'apply' || 'plan' }} validate: true format: true plan-encrypt: ${{ secrets.TF_PLAN_PASSPHRASE }} hide-args: var=,var-file= arg-lock: ${{ github.event_name == 'push' }} ``` -------------------------------- ### Expand Summary Section by Default Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/inputs.md Expands the collapsible summary section in the PR comment by default. ```yaml expand-summary: false ``` -------------------------------- ### List Artifacts Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/github-api-integration.md Find plan file artifacts by name. This endpoint is used to retrieve information about artifacts, specifically filtering by artifact name. ```APIDOC ## GET /repos/{owner}/{repo}/actions/artifacts ### Description Find plan file artifacts by name. This endpoint is used to retrieve information about artifacts, specifically filtering by artifact name. ### Method GET ### Endpoint /repos/{owner}/{repo}/actions/artifacts ### Parameters #### Query Parameters - **name** (string) - Optional - Artifact name to filter (optional, uses field) ### Response #### Success Response (200) - **artifacts** (array) - List of artifact objects. - **total_count** (integer) - The total number of artifacts. ### Response Example ```json { "artifacts": [ { "id": 123456, "name": "terraform-456-abc123.tfplan.encrypted", "size_in_bytes": 15000, "url": "...", "archive_download_url": "...", "status": "completed", "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z", "expires_at": "2024-04-15T10:30:00Z" } ], "total_count": 1 } ``` ``` -------------------------------- ### Custom Diff Processing in GitHub Actions Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/diff-generation.md Demonstrates how to process the diff output from a Terraform action within a GitHub Actions workflow. It shows capturing the diff output and applying custom transformations using sed. ```yaml - id: tf uses: op5dev/tf-via-pr@v13 with: command: plan - name: Custom diff processing run: | diff="${{ steps.tf.outputs.diff }}" # Custom processing custom_diff=$(echo "$diff" | sed 's/+/✅/g; s/-/❌/g') echo "$custom_diff" ``` -------------------------------- ### Import GitHub Actions Core SDK Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/nodejs-entry-point.md Imports the @actions/core module for interacting with the GitHub Actions environment, including logging and error handling. ```typescript import * as core from "@actions/core"; ``` -------------------------------- ### Verify Pull Request Existence Source: https://github.com/op5dev/tf-via-pr/blob/main/_autodocs/troubleshooting.md Command to check if a specific pull request exists. ```bash gh pr view $PR_NUMBER ```