This commit is contained in:
2025-11-07 20:40:19 -05:00
parent 0946ca0e7f
commit 13ee7a84e1
2 changed files with 98 additions and 206 deletions
+23 -56
View File
@@ -1,76 +1,43 @@
name: "Terraform/OpenTofu PR Commenter" name: "Terraform/OpenTofu PR Commenter"
description: "Posts Terraform/OpenTofu `fmt`, `init`, `plan`, or `validate` results as PR comments on GitHub or Gitea." description: "Posts PR comments for Terraform or OpenTofu commands (init/plan/fmt/validate), compatible with Gitea and GitHub."
author: "Charish Patel" author: "Trez"
branding:
icon: "message-square"
color: "purple"
inputs: inputs:
command: commenter_type:
description: "The command type: fmt | init | plan | validate" description: "The Terraform/OpenTofu command type (e.g., init, plan, fmt, validate)"
required: true required: true
commenter_input: commenter_input:
description: "Stdout or file list from previous Terraform/OpenTofu step" description: "Captured stdout/stderr output of the Terraform/OpenTofu command"
required: true required: true
commenter_exitcode: commenter_exitcode:
description: "Exit code from previous Terraform/OpenTofu step" description: "Exit code of the Terraform/OpenTofu command"
required: true required: true
pr_number: working_dir:
description: "PR number" description: "Optional working directory relative to the repository root (e.g., cloudflare)"
required: false
pr_comments_url:
description: "URL for PR comments API"
required: false
pr_comment_uri:
description: "URI for individual PR comment API"
required: false required: false
github_token: github_token:
description: "GitHub token (if running in GitHub Actions)" description: "Token used for posting the comment (Gitea or GitHub)"
required: false required: true
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: ""
runs: runs:
using: "composite" using: "composite"
steps: steps:
- name: Run TF/Tofu PR Commenter - name: Run Terraform/OpenTofu PR Commenter
shell: bash shell: bash
run: | run: |
pwd ; echo -e "${{ github.action_path }}" chmod +x "${{ github.action_path }}/tf-pr-comment.sh"
chmod +x ${{ github.action_path }}/tf-pr-comment.sh "${{ github.action_path }}/tf-pr-comment.sh" \
${{ github.action_path }}/tf-pr-comment.sh \ "${{ inputs.commenter_type }}" \
"${{ inputs.command }}" \
"${{ inputs.commenter_input }}" \ "${{ inputs.commenter_input }}" \
"${{ inputs.commenter_exitcode }}" \ "${{ inputs.commenter_exitcode }}" \
"${{ inputs.working_directory }}" "${{ inputs.working_dir }}"
env: 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 }} GITHUB_TOKEN: ${{ inputs.github_token }}
GITEA_TOKEN: ${{ inputs.gitea_token }} PR_NUMBER: ${{ env.PR_NUMBER }}
GITEA_ACTION: ${{ inputs.gitea_action }} PR_URL: ${{ env.PR_URL }}
GITEA_API_URL: ${{ inputs.gitea_api_url }} PR_COMMENTS_URL: ${{ env.PR_COMMENTS_URL }}
GITEA_REPOSITORY: ${{ inputs.gitea_repository }} PR_COMMENT_ID: ${{ env.PR_COMMENT_ID }}
HIGHLIGHT_CHANGES: ${{ inputs.highlight_changes }} PR_COMMENT_URI: ${{ env.PR_COMMENT_URI }}
TF_WORKSPACE: ${{ inputs.tf_workspace }}
+75 -150
View File
@@ -1,164 +1,89 @@
#!/usr/bin/env bash #!/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" export PATH="${PATH}:/home/runner/.opentofu/bin"
# Read inputs # === Detect tofu / terraform command =================================
COMMAND=$1 if command -v tofu >/dev/null 2>&1; then
INPUT=$2 TOFU_CMD="tofu"
EXIT_CODE=$3 elif command -v terraform >/dev/null 2>&1; then
WORKING_DIR=$4 TOFU_CMD="terraform"
# 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; }
else else
cd "$REPO_ROOT" || { echo "Cannot determine repo root"; exit 1; } echo "❌ Neither 'tofu' nor 'terraform' found in PATH."
exit 1
fi fi
# Strip ANSI codes from input echo "🧰 Using IaC command: $TOFU_CMD"
# INPUT=$(echo "$INPUT" | sed 's/\x1b\[[0-9;]*m//g')
################## # === Validation ======================================================
# CI Detection if [[ -z "${COMMENTER_TYPE}" ]]; then
################## echo "❌ commenter_type input is required."
if [[ -n "$GITHUB_ACTIONS" ]]; then exit 1
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
fi fi
ACCEPT_HEADER="Accept: application/vnd.github.v3+json" # === Prepare Comment Body ============================================
CONTENT_HEADER="Content-Type: application/json" EXIT_STATUS_MSG=""
if [[ "$COMMENTER_EXITCODE" -eq 0 ]]; then
################## EXIT_STATUS_MSG="${COMMENTER_TYPE^} succeeded."
# Shared Settings else
################## EXIT_STATUS_MSG="${COMMENTER_TYPE^} failed with exit code ${COMMENTER_EXITCODE}."
DETAILS_STATE=" open" fi
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
<details$DETAILS_STATE><summary><code>$file</code></summary>
$DIFF_BLOCK
</details>"
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\`
<details$DETAILS_STATE><summary>Show Output</summary>
$PR_OUTPUT
</details>"
handle_pr_comment "$COMMAND" "$PR_COMMENT"
;;
init|validate)
STATUS="Succeeded"
[[ "$COMMENTER_EXITCODE" -ne 0 ]] && STATUS="Failed"
PR_COMMENT="### tofu \`$COMMAND\` $STATUS for Workspace: \`$WORKSPACE\`
<details$DETAILS_STATE><summary>Show Output</summary>
# Format comment body
COMMENT_BODY="### ${COMMENTER_TYPE^} Results
\`\`\` \`\`\`
$COMMENTER_INPUT ${COMMENTER_INPUT}
\`\`\` \`\`\`
</details>" ${EXIT_STATUS_MSG}
handle_pr_comment "$COMMAND" "$PR_COMMENT" "
;;
*) # === Post Comment ====================================================
echo "Unsupported command: $COMMAND" echo "📝 Posting PR comment to: ${PR_COMMENTS_URL:-N/A}"
exit 1
;; if [[ -z "${PR_COMMENTS_URL:-}" ]]; then
esac 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."