Initial commit.
This commit is contained in:
+73
@@ -0,0 +1,73 @@
|
|||||||
|
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"
|
||||||
|
|
||||||
|
# Define the inputs
|
||||||
|
inputs:
|
||||||
|
command:
|
||||||
|
description: "The command type: fmt | init | plan | validate"
|
||||||
|
required: true
|
||||||
|
commenter_input:
|
||||||
|
description: "Stdout or file list from previous Terraform/OpenTofu step"
|
||||||
|
required: true
|
||||||
|
commenter_exitcode:
|
||||||
|
description: "Exit code from previous Terraform/OpenTofu step"
|
||||||
|
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"
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
# Define the action type
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Run TF/Tofu PR Commenter
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
chmod +x ${{ github.action_path }}/tf-pr-comment.sh
|
||||||
|
${{ github.action_path }}/tf-pr-comment.sh "${{ inputs.command }}" "${{ inputs.commenter_input }}" "${{ inputs.commenter_exitcode }}"
|
||||||
|
env:
|
||||||
|
# PR Environment Variables
|
||||||
|
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 }}
|
||||||
|
# Optional highlighting
|
||||||
|
HIGHLIGHT_CHANGES: ${{ inputs.highlight_changes }}
|
||||||
|
TF_WORKSPACE: ${{ inputs.tf_workspace }}
|
||||||
|
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
##################
|
||||||
|
# Inputs
|
||||||
|
##################
|
||||||
|
COMMAND="$1" # fmt | init | plan | validate
|
||||||
|
COMMENTER_INPUT="$2" # stdout/stderr output OR newline-separated file list (for fmt)
|
||||||
|
COMMENTER_EXITCODE="$3" # exit code from previous step
|
||||||
|
WORKSPACE="${TF_WORKSPACE:-default}"
|
||||||
|
|
||||||
|
##################
|
||||||
|
# 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
|
||||||
|
<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>
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
$COMMENTER_INPUT
|
||||||
|
\`\`\`
|
||||||
|
</details>"
|
||||||
|
handle_pr_comment "$COMMAND" "$PR_COMMENT"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unsupported command: $COMMAND"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user