#!/usr/bin/env bash set -e # Add OpenTofu binary to PATH 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; } else cd "$REPO_ROOT" || { echo "Cannot determine repo root"; exit 1; } fi # Strip ANSI codes from input # INPUT=$(echo "$INPUT" | sed 's/\x1b\[[0-9;]*m//g') ################## # 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 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 \`\`\` $COMMENTER_INPUT \`\`\` " handle_pr_comment "$COMMAND" "$PR_COMMENT" ;; *) echo "Unsupported command: $COMMAND" exit 1 ;; esac