From 13ee7a84e18aa743d45318825bb5394705a9822e Mon Sep 17 00:00:00 2001 From: "Trez.One" Date: Fri, 7 Nov 2025 20:40:19 -0500 Subject: [PATCH] ... --- action.yml | 79 +++++------------ tf-pr-comment.sh | 225 ++++++++++++++++------------------------------- 2 files changed, 98 insertions(+), 206 deletions(-) diff --git a/action.yml b/action.yml index f971df9..5afd42a 100644 --- a/action.yml +++ b/action.yml @@ -1,76 +1,43 @@ name: "Terraform/OpenTofu PR Commenter" -description: "Posts Terraform/OpenTofu `fmt`, `init`, `plan`, or `validate` results as PR comments on GitHub or Gitea." -author: "Charish Patel" +description: "Posts PR comments for Terraform or OpenTofu commands (init/plan/fmt/validate), compatible with Gitea and GitHub." +author: "Trez" +branding: + icon: "message-square" + color: "purple" inputs: - command: - description: "The command type: fmt | init | plan | validate" + commenter_type: + description: "The Terraform/OpenTofu command type (e.g., init, plan, fmt, validate)" required: true commenter_input: - description: "Stdout or file list from previous Terraform/OpenTofu step" + description: "Captured stdout/stderr output of the Terraform/OpenTofu command" required: true commenter_exitcode: - description: "Exit code from previous Terraform/OpenTofu step" + description: "Exit code of the Terraform/OpenTofu command" required: true - pr_number: - description: "PR number" - required: false - pr_comments_url: - description: "URL for PR comments API" - required: false - pr_comment_uri: - description: "URI for individual PR comment API" + working_dir: + description: "Optional working directory relative to the repository root (e.g., cloudflare)" required: false github_token: - description: "GitHub token (if running in GitHub Actions)" - required: false - gitea_token: - description: "Gitea token (if running in Gitea Actions)" - required: false - gitea_action: - description: "Set to true if running in Gitea Actions" - required: false - default: "false" - gitea_api_url: - description: "Gitea API URL" - required: false - gitea_repository: - description: "Gitea repository in format owner/repo" - required: false - highlight_changes: - description: "Set to false to disable diff highlighting" - required: false - default: "true" - tf_workspace: - description: "Terraform/OpenTofu workspace (default: 'default')" - required: false - default: default - working_directory: - description: "Optional working directory relative to repo root; if set, script runs there" - required: false - default: "" + description: "Token used for posting the comment (Gitea or GitHub)" + required: true runs: using: "composite" steps: - - name: Run TF/Tofu PR Commenter + - name: Run Terraform/OpenTofu PR Commenter shell: bash run: | - pwd ; echo -e "${{ github.action_path }}" - chmod +x ${{ github.action_path }}/tf-pr-comment.sh - ${{ github.action_path }}/tf-pr-comment.sh \ - "${{ inputs.command }}" \ + chmod +x "${{ github.action_path }}/tf-pr-comment.sh" + "${{ github.action_path }}/tf-pr-comment.sh" \ + "${{ inputs.commenter_type }}" \ "${{ inputs.commenter_input }}" \ "${{ inputs.commenter_exitcode }}" \ - "${{ inputs.working_directory }}" + "${{ inputs.working_dir }}" env: - PR_NUMBER: ${{ inputs.pr_number }} - PR_COMMENTS_URL: ${{ inputs.pr_comments_url }} - PR_COMMENT_URI: ${{ inputs.pr_comment_uri }} GITHUB_TOKEN: ${{ inputs.github_token }} - GITEA_TOKEN: ${{ inputs.gitea_token }} - GITEA_ACTION: ${{ inputs.gitea_action }} - GITEA_API_URL: ${{ inputs.gitea_api_url }} - GITEA_REPOSITORY: ${{ inputs.gitea_repository }} - HIGHLIGHT_CHANGES: ${{ inputs.highlight_changes }} - TF_WORKSPACE: ${{ inputs.tf_workspace }} + PR_NUMBER: ${{ env.PR_NUMBER }} + PR_URL: ${{ env.PR_URL }} + PR_COMMENTS_URL: ${{ env.PR_COMMENTS_URL }} + PR_COMMENT_ID: ${{ env.PR_COMMENT_ID }} + PR_COMMENT_URI: ${{ env.PR_COMMENT_URI }} diff --git a/tf-pr-comment.sh b/tf-pr-comment.sh index a6ad6f8..ebef9d0 100644 --- a/tf-pr-comment.sh +++ b/tf-pr-comment.sh @@ -1,164 +1,89 @@ #!/usr/bin/env bash -set -e +set -euo pipefail -# Add OpenTofu binary to PATH +# === Inputs =========================================================== +COMMENTER_TYPE="${1:-}" +COMMENTER_INPUT="${2:-}" +COMMENTER_EXITCODE="${3:-0}" +WORKING_DIR="${4:-}" + +# === Move into working directory if specified ======================== +if [[ -n "$WORKING_DIR" ]]; then + echo "🔹 Changing to working directory: $WORKING_DIR" + cd "${GITHUB_WORKSPACE}/${WORKING_DIR}" || { + echo "❌ Error: Cannot change to working directory '${WORKING_DIR}'" + exit 1 + } +else + cd "${GITHUB_WORKSPACE:-.}" +fi + +# === Environment Debug Info ========================================== +echo "📁 Current working directory: $(pwd)" +echo "📦 Repository root: ${GITHUB_WORKSPACE:-N/A}" + +# === Setup PATH for OpenTofu ========================================= export PATH="${PATH}:/home/runner/.opentofu/bin" -# Read inputs -COMMAND=$1 -INPUT=$2 -EXIT_CODE=$3 -WORKING_DIR=$4 - -# Determine repo root (where .git exists) -REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD") - -# Change to working directory if provided, relative to repo root -if [[ -n "$WORKING_DIR" ]]; then - TARGET_DIR="$REPO_ROOT/$WORKING_DIR" - echo "Switching to working directory: $TARGET_DIR" - cd "$TARGET_DIR" || { echo "Directory $TARGET_DIR not found"; exit 1; } +# === Detect tofu / terraform command ================================= +if command -v tofu >/dev/null 2>&1; then + TOFU_CMD="tofu" +elif command -v terraform >/dev/null 2>&1; then + TOFU_CMD="terraform" else - cd "$REPO_ROOT" || { echo "Cannot determine repo root"; exit 1; } + echo "❌ Neither 'tofu' nor 'terraform' found in PATH." + exit 1 fi -# Strip ANSI codes from input -# INPUT=$(echo "$INPUT" | sed 's/\x1b\[[0-9;]*m//g') +echo "🧰 Using IaC command: $TOFU_CMD" -################## -# CI Detection -################## -if [[ -n "$GITHUB_ACTIONS" ]]; then - CI_PLATFORM="github" -elif [[ -n "$GITEA_ACTION" ]]; then - CI_PLATFORM="gitea" -else - CI_PLATFORM="local" -fi -echo "Detected CI platform: $CI_PLATFORM" - -################## -# PR Variables -################## -if [[ "$CI_PLATFORM" == "github" ]]; then - : "${PR_NUMBER:?PR_NUMBER not set}" - : "${PR_COMMENTS_URL:?PR_COMMENTS_URL not set}" - : "${PR_COMMENT_URI:?PR_COMMENT_URI not set}" - AUTH_HEADER="Authorization: token $GITHUB_TOKEN" -elif [[ "$CI_PLATFORM" == "gitea" ]]; then - : "${PR_NUMBER:?PR_NUMBER not set}" - : "${PR_COMMENTS_URL:?PR_COMMENTS_URL not set}" - : "${PR_COMMENT_URI:?PR_COMMENT_URI not set}" - : "${GITEA_TOKEN:?GITEA_TOKEN not set}" - AUTH_HEADER="Authorization: token $GITEA_TOKEN" -else - echo "Local mode: PR variables must be set manually." - exit 1 +# === Validation ====================================================== +if [[ -z "${COMMENTER_TYPE}" ]]; then + echo "❌ commenter_type input is required." + exit 1 fi -ACCEPT_HEADER="Accept: application/vnd.github.v3+json" -CONTENT_HEADER="Content-Type: application/json" - -################## -# Shared Settings -################## -DETAILS_STATE=" open" -COLOURISE=${HIGHLIGHT_CHANGES:-true} - -################## -# Helper Functions -################## -handle_pr_comment() { - local type="$1" - local body="$2" - - PR_COMMENT_ID=$(curl -sS -H "$AUTH_HEADER" -H "$ACCEPT_HEADER" -L "$PR_COMMENTS_URL" \ - | jq ".[] | select(.body|test(\"### tofu \\\`$type\\\`\")) | .id") - - if [[ "$PR_COMMENT_ID" ]]; then - echo "Updating existing $type PR comment: $PR_COMMENT_ID" - PR_COMMENT_URL="$PR_COMMENT_URI/$PR_COMMENT_ID" - PR_PAYLOAD=$(jq -n --arg body "$body" '{body: $body}') - curl -sS -X PATCH -H "$AUTH_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_HEADER" \ - -d "$PR_PAYLOAD" -L "$PR_COMMENT_URL" > /dev/null - else - echo "Creating new $type PR comment" - PR_PAYLOAD=$(jq -n --arg body "$body" '{body: $body}') - curl -sS -X POST -H "$AUTH_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_HEADER" \ - -d "$PR_PAYLOAD" -L "$PR_COMMENTS_URL" > /dev/null - fi -} - -format_diff_block() { - local content="$1" - local codeblock="" - if [[ $CI_PLATFORM == "github" && $COLOURISE == "true" ]]; then - content=$(echo "$content" | sed -r 's/^~/!/g') - codeblock="diff" - fi - echo "```$codeblock -$content -```" -} - -################## -# Command Handlers -################## -case "$COMMAND" in - -fmt) - STATUS="Succeeded" - [[ "$COMMENTER_EXITCODE" -ne 0 ]] && STATUS="Failed" - - ALL_DIFFS="" - # COMMENTER_INPUT is expected to be a newline-separated file list - while IFS= read -r file; do - if [[ -n "$file" && -f "$file" ]]; then - FILE_DIFF=$(tofu fmt -no-color -write=false -diff "$file" 2>/dev/null || true) - DIFF_BLOCK=$(format_diff_block "$FILE_DIFF") - ALL_DIFFS="$ALL_DIFFS -$file - -$DIFF_BLOCK -" - fi - done <<< "$COMMENTER_INPUT" - - # Fallback if no valid files found - [[ -z "$ALL_DIFFS" ]] && ALL_DIFFS=$(format_diff_block "$COMMENTER_INPUT") - - PR_COMMENT="### tofu \`fmt\` $STATUS for Workspace: \`$WORKSPACE\` -$ALL_DIFFS" - handle_pr_comment "$COMMAND" "$PR_COMMENT" - ;; - -plan) - STATUS="Succeeded" - [[ "$COMMENTER_EXITCODE" -ne 0 ]] && STATUS="Failed" - PR_OUTPUT=$(format_diff_block "$COMMENTER_INPUT") - PR_COMMENT="### tofu \`plan\` $STATUS for Workspace: \`$WORKSPACE\` -Show Output - -$PR_OUTPUT -" - handle_pr_comment "$COMMAND" "$PR_COMMENT" - ;; - -init|validate) - STATUS="Succeeded" - [[ "$COMMENTER_EXITCODE" -ne 0 ]] && STATUS="Failed" - PR_COMMENT="### tofu \`$COMMAND\` $STATUS for Workspace: \`$WORKSPACE\` -Show Output +# === Prepare Comment Body ============================================ +EXIT_STATUS_MSG="" +if [[ "$COMMENTER_EXITCODE" -eq 0 ]]; then + EXIT_STATUS_MSG="✅ ${COMMENTER_TYPE^} succeeded." +else + EXIT_STATUS_MSG="❌ ${COMMENTER_TYPE^} failed with exit code ${COMMENTER_EXITCODE}." +fi +# Format comment body +COMMENT_BODY="### ${COMMENTER_TYPE^} Results \`\`\` -$COMMENTER_INPUT +${COMMENTER_INPUT} \`\`\` -" - handle_pr_comment "$COMMAND" "$PR_COMMENT" - ;; +${EXIT_STATUS_MSG} +" -*) - echo "Unsupported command: $COMMAND" - exit 1 - ;; -esac +# === Post Comment ==================================================== +echo "📝 Posting PR comment to: ${PR_COMMENTS_URL:-N/A}" + +if [[ -z "${PR_COMMENTS_URL:-}" ]]; then + echo "❌ Missing PR_COMMENTS_URL environment variable." + exit 1 +fi + +# Update comment if comment_id exists, otherwise create a new one +if [[ -n "${PR_COMMENT_ID:-}" && -n "${PR_COMMENT_URI:-}" ]]; then + echo "🌀 Updating existing comment (ID: ${PR_COMMENT_ID})" + curl -sS -X PATCH \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$(jq -n --arg body "$COMMENT_BODY" '{body: $body}')" \ + "${PR_COMMENT_URI}" \ + || echo "⚠️ Failed to update existing comment." +else + echo "🆕 Creating a new PR comment" + curl -sS -X POST \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$(jq -n --arg body "$COMMENT_BODY" '{body: $body}')" \ + "${PR_COMMENTS_URL}" \ + || echo "⚠️ Failed to create PR comment." +fi + +echo "✅ Comment posted successfully."