From 469b0bc9a483ea03f55ae3a3f96a8870c1d13b59 Mon Sep 17 00:00:00 2001 From: Aaron Batilo <54044698+abatilo-isp@users.noreply.github.com> Date: Thu, 27 Aug 2020 11:11:29 -0700 Subject: [PATCH] feat: Helmfile composite GitHub actions (#7) * feat: Helmfile composite GitHub actions These are the scripts that ultimately make up a composite GitHub Action for running helmfile while having status codes propagated in a more intuitive way, on top of wrapping all of the edge cases for formatting comment text back to a GH PR comment. --- helmfile-actions/README.md | 35 +++++++++++++++++++++ helmfile-actions/action.yml | 19 ++++++++++++ helmfile-actions/apply.sh | 16 ++++++++++ helmfile-actions/diff.sh | 61 +++++++++++++++++++++++++++++++++++++ helmfile-actions/main.sh | 29 ++++++++++++++++++ 5 files changed, 160 insertions(+) create mode 100644 helmfile-actions/README.md create mode 100644 helmfile-actions/action.yml create mode 100644 helmfile-actions/apply.sh create mode 100644 helmfile-actions/diff.sh create mode 100755 helmfile-actions/main.sh diff --git a/helmfile-actions/README.md b/helmfile-actions/README.md new file mode 100644 index 0000000..fe05a0b --- /dev/null +++ b/helmfile-actions/README.md @@ -0,0 +1,35 @@ +# helmfile-actions + +There is a single `./main.sh` file that delegates down to other scripts based on the `command` that you pass in. + +## Inputs +```yaml +inputs: + command: + description: "The helmfile command to run" + required: true + working_directory: + description: "The directory to run all the commands in" + required: false + default: "." +``` + +## Examples +Example usage of `helmfile diff`: +```yaml +- uses: iStreamPlanet/github-actions/helmfile-actions@main + if: github.event_name == 'pull_request' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + command: diff + working_directory: helmfile/ +``` + +Example usage of `helmfile apply`: +```yaml +- uses: iStreamPlanet/github-actions/helmfile-actions@main + with: + command: apply + working_directory: helmfile/ +``` diff --git a/helmfile-actions/action.yml b/helmfile-actions/action.yml new file mode 100644 index 0000000..8bc8587 --- /dev/null +++ b/helmfile-actions/action.yml @@ -0,0 +1,19 @@ +name: "helmfile action" +description: "A composite action wrapper around helmfile" +inputs: + command: + description: "The helmfile command to run" + required: true + working_directory: + description: "The directory to run all the commands in" + required: false + default: "." +outputs: {} +runs: + using: "composite" + steps: + - name: helmfile + shell: bash + id: main + working-directory: ${{ inputs.working_directory }} + run: ${{ github.action_path }}/main.sh "${{ inputs.command }}" "${{ inputs.working_directory }}" diff --git a/helmfile-actions/apply.sh b/helmfile-actions/apply.sh new file mode 100644 index 0000000..4685859 --- /dev/null +++ b/helmfile-actions/apply.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +function helmfileApply { + output=$(helmfile --no-color apply ${*} 2>&1) + exitCode=$? + + if [ ${exitCode} -eq 0 ]; then + echo "Successfully ran helmfile apply command." + else + echo "Error: Failed to run helmfile diff" + fi + + echo "${output}" + echo + exit ${exitCode} +} diff --git a/helmfile-actions/diff.sh b/helmfile-actions/diff.sh new file mode 100644 index 0000000..335c8f2 --- /dev/null +++ b/helmfile-actions/diff.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +function helmfileDiff { + output=$(helmfile --no-color diff --detailed-exitcode ${*} 2>&1) + exitCode=$? + hasChanges=false + commentStatus="Failed" + + if [ ${exitCode} -eq 0 ]; then + echo "Successfully ran helmfile diff command. No changes were found" + echo "${output}" + echo + echo "::set-output name=has-changes::${hasChanges}" + exit ${exitCode} + fi + + if [ ${exitCode} -eq 2 ]; then + # This should still be a success + exitCode=0 + hasChanges=true + commentStatus="Success" + + echo "Successfully ran helmfile diff command. Changes were found" + echo "${output}" + echo + + # If output is longer than max length (65536 characters), keep last part + output=$(echo "${output}" | tail -c 65000 ) + fi + + if [ ${exitCode} -ne 0 ]; then + echo "Error: Failed to run helmfile diff" + echo "${output}" + echo + fi + + if [ "$GITHUB_EVENT_NAME" == "pull_request" ] && ([ "${hasChanges}" == "true" ] || [ "${commentStatus}" == "Failed" ]); then + commentWrapper="#### \`helmfile diff\` ${commentStatus} for \`${workingDir}\` +
Show Output + +\`\`\`diff +${output} +\`\`\` + +
+" + + payload=$(echo "${commentWrapper}" | jq -R --slurp '{body: .}') + commentsURL=$(cat ${GITHUB_EVENT_PATH} | jq -r .pull_request.comments_url) + echo "${payload}" | curl -s -S -H "Authorization: token ${GITHUB_TOKEN}" --header "Content-Type: application/json" --data @- "${commentsURL}" > /dev/null + fi + + echo "::set-output name=has-changes::${hasChanges}" + + # https://github.community/t5/GitHub-Actions/set-output-Truncates-Multiline-Strings/m-p/38372/highlight/true#M3322 + output="${output//'%'/'%25'}" + output="${output//$'\n'/'%0A'}" + output="${output//$'\r'/'%0D'}" + echo "::set-output name=output::${output}" + exit ${exitCode} +} diff --git a/helmfile-actions/main.sh b/helmfile-actions/main.sh new file mode 100755 index 0000000..f460370 --- /dev/null +++ b/helmfile-actions/main.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +if [ "$#" -ne 2 ]; then + echo 'Usage: ./main.sh $command $working_directory' + exit 1 +fi + +workingDir="$2" +function main { + command="$1" + scriptDir=$(dirname ${0}) + source ${scriptDir}/diff.sh + source ${scriptDir}/apply.sh + + case "${command}" in + diff) + helmfileDiff + ;; + apply) + helmfileApply + ;; + *) + echo "Error: Unrecognized command ${command}" + exit 1 + ;; + esac +} + +main "$1"