diff --git a/.circleci/test-deploy.yml b/.circleci/test-deploy.yml index 164b900a..920f7f97 100644 --- a/.circleci/test-deploy.yml +++ b/.circleci/test-deploy.yml @@ -17,6 +17,7 @@ jobs: steps: - checkout - slack/notify: + debug: true step_name: "Custom template with group mention" event: always custom: | @@ -43,23 +44,28 @@ jobs: command: | grep "pass" /tmp/SLACK_JOB_STATUS - slack/notify: + debug: true step_name: "Fail template with mentions" template: basic_fail_1 mentions: "@orbs" event: always - slack/notify: + debug: true step_name: "Success template with mentions" template: basic_success_1 event: always - slack/notify: + debug: true step_name: "Success tagged template" template: success_tagged_deploy_1 event: always - slack/notify: + debug: true step_name: "Basic on hold template" template: basic_on_hold_1 event: always - slack/notify: + debug: true step_name: "Custom template with env var in the message" event: pass custom: > @@ -74,11 +80,6 @@ jobs: } ] } - - slack/notify: - step_name: "Notify with debug set to true" - debug: true - template: basic_success_1 - event: always - run: name: Dynamically populate the mention and export the template as an environment variable command: | @@ -86,13 +87,16 @@ jobs: echo 'export SLACK_PARAM_MENTIONS="$COMMIT_MESSAGE"' >> $BASH_ENV echo 'export MY_ORB_TEMPLATE=$(cat src/message_templates/basic_success_1.json)' >> $BASH_ENV - slack/notify: + debug: true step_name: "Dynamic template with environment variable" event: always template: MY_ORB_TEMPLATE - slack/notify: + debug: true step_name: "Notify without template parameter" # Should run for every branch but master - slack/notify: + debug: true step_name: "Invert match set to true on 'master' branch pattern" branch_pattern: "master" invert_match: true @@ -101,6 +105,7 @@ jobs: command: | printf '%s\n' 'export MULTILINE_STRING=$(printf "%s\\n" "Line 1." "Line 2." "Line 3.")' >> "$BASH_ENV" - slack/notify: + debug: true step_name: "Notify with multiline string" event: pass custom: > @@ -120,6 +125,7 @@ jobs: command: | printf '%s\n' 'export DOUBLE_QUOTES_STRING=$(printf "%s\\n" "Hello There! My name is \"Potato\"")' >> "$BASH_ENV" - slack/notify: + debug: true step_name: "Notify with double-quoted string" event: pass custom: > @@ -139,9 +145,9 @@ jobs: command: | printf '%s\n' 'export BACKSLASHES_STRING="This is how a \ looks like"' >> "$BASH_ENV" - slack/notify: + debug: true step_name: "Notify with backslashes string" event: pass - debug: true custom: > { "blocks": [ @@ -163,7 +169,7 @@ workflows: filters: *filters matrix: parameters: - runner: [cimg, mac, alpine] + runner: [cimg, mac, alpine, windows] - orb-tools/lint: filters: *filters - orb-tools/pack: @@ -198,3 +204,8 @@ executors: # This image contains both CURL and JQ docker: - image: dwdraju/alpine-curl-jq + windows: + machine: + image: windows-server-2019-vs2019:current + resource_class: windows.medium + shell: bash.exe diff --git a/src/commands/notify.yml b/src/commands/notify.yml index 88743760..1c0d63c2 100644 --- a/src/commands/notify.yml +++ b/src/commands/notify.yml @@ -103,9 +103,11 @@ steps: SLACK_PARAM_IGNORE_ERRORS: "<>" SLACK_PARAM_DEBUG: "<>" SLACK_PARAM_CIRCLECI_HOST: "<>" + SLACK_SCRIPT_NOTIFY: "<>" + SLACK_SCRIPT_UTILS: "<>" # import pre-built templates using the orb-pack local script include. basic_fail_1: "<>" success_tagged_deploy_1: "<>" basic_on_hold_1: "<>" basic_success_1: "<>" - command: <> + command: <> diff --git a/src/scripts/main.sh b/src/scripts/main.sh new file mode 100644 index 00000000..2e461487 --- /dev/null +++ b/src/scripts/main.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +# Workaround for Windows Support +# For details, see: https://github.com/CircleCI-Public/slack-orb/pull/380 +# shellcheck source=/dev/null +eval printf '%s' "$SLACK_SCRIPT_NOTIFY" diff --git a/src/scripts/notify.sh b/src/scripts/notify.sh index db875750..f489c2b2 100644 --- a/src/scripts/notify.sh +++ b/src/scripts/notify.sh @@ -1,6 +1,8 @@ #!/bin/sh # shellcheck disable=SC2016,SC3043 +# Import utils. +eval "$SLACK_SCRIPT_UTILS" JQ_PATH=/usr/local/bin/jq BuildMessageBody() { @@ -9,7 +11,7 @@ BuildMessageBody() { # if none is supplied, check for a pre-selected template value. # If none, error. if [ -n "${SLACK_PARAM_CUSTOM:-}" ]; then - SanitizeVars "$SLACK_PARAM_CUSTOM" + SanitizeVars "$SLACK_PARAM_CUSTOM" ModifyCustomTemplate # shellcheck disable=SC2016 CUSTOM_BODY_MODIFIED=$(echo "$CUSTOM_BODY_MODIFIED" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed 's/`/\\`/g') @@ -30,7 +32,7 @@ BuildMessageBody() { T1="$(printf '%s' "$template_body" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed 's/`/\\`/g')" T2="$(eval printf '%s' \""$T1"\")" fi - + # Insert the default channel. THIS IS TEMPORARY T2="$(printf '%s' "$T2" | jq ". + {\"channel\": \"$SLACK_DEFAULT_CHANNEL\"}")" SLACK_MSG_BODY="$T2" @@ -181,20 +183,11 @@ SetupLogs() { fi } -ExitIfWindows() { - os="$(uname -s | tr '[:upper:]' '[:lower:]')" - if printf '%s\n' "$os" | grep -q 'msys*\|cygwin*' ; then - printf '%s\n' "Windows is not supported by this orb." - printf '%s\n' "For more information, see: https://github.com/CircleCI-Public/slack-orb/wiki/FAQ." - exit 1 - fi -} - # $1: Template with environment variables to be sanitized. SanitizeVars() { [ -z "$1" ] && { printf '%s\n' "Missing argument."; return 1; } local template="$1" - + # Find all environment variables in the template with the format $VAR or ${VAR}. # The "|| true" is to prevent bats from failing when no matches are found. local variables @@ -204,23 +197,30 @@ SanitizeVars() { # Extract the variable names from the matches. local variable_names variable_names="$(printf '%s\n' "$variables" | grep -o -E '[a-zA-Z0-9_]+')" - + + # Find out what OS we're running on. + detect_os + for var in $variable_names; do # The variable must be wrapped in double quotes before the evaluation. # Otherwise the newlines will be removed. local value value="$(eval printf '%s' \"\$"$var\"")" [ -z "$value" ] && { printf '%s\n' "$var is empty or doesn't exist. Skipping it..."; continue; } - + printf '%s\n' "Sanitizing $var..." - + local sanitized_value="$value" # Escape backslashes. sanitized_value="$(printf '%s' "$sanitized_value" | awk '{gsub(/\\/, "&\\"); print $0}')" # Escape newlines. sanitized_value="$(printf '%s' "$sanitized_value" | awk 'NR > 1 { printf("\\n") } { printf("%s", $0) }')" # Escape double quotes. - sanitized_value="$(printf '%s' "$sanitized_value" | awk '{gsub(/\"/, "\\\""); print $0}')" + if [ "$PLATFORM" = "windows" ]; then + sanitized_value="$(printf '%s' "$sanitized_value" | awk '{gsub(/"/, "\\\""); print $0}')" + else + sanitized_value="$(printf '%s' "$sanitized_value" | awk '{gsub(/\"/, "\\\""); print $0}')" + fi # Write the sanitized value back to the original variable. # shellcheck disable=SC3045 # This is working on Alpine. @@ -234,7 +234,6 @@ SanitizeVars() { # This is done so this script may be tested. ORB_TEST_ENV="bats-core" if [ "${0#*"$ORB_TEST_ENV"}" = "$0" ]; then - ExitIfWindows # shellcheck source=/dev/null . "/tmp/SLACK_JOB_STATUS" ShouldPost diff --git a/src/scripts/utils.sh b/src/scripts/utils.sh new file mode 100644 index 00000000..b6f25378 --- /dev/null +++ b/src/scripts/utils.sh @@ -0,0 +1,25 @@ +#!/bin/false +# shellcheck shell=sh +# shellcheck disable=SC2154 + +detect_os() { + detected_platform="$(uname -s | tr '[:upper:]' '[:lower:]')" + + case "$detected_platform" in + linux*) + PLATFORM=linux + ;; + darwin*) + PLATFORM=macos + ;; + msys*|cygwin*) + PLATFORM=windows + ;; + *) + printf '%s\n' "Unsupported OS: \"$platform\"." + exit 1 + ;; + esac + + export readonly PLATFORM +} diff --git a/src/tests/notify.bats b/src/tests/notify.bats index f8eae6dc..ebd93deb 100644 --- a/src/tests/notify.bats +++ b/src/tests/notify.bats @@ -2,6 +2,7 @@ setup() { source ./src/scripts/notify.sh + source ./src/scripts/utils.sh export SLACK_PARAM_BRANCHPATTERN=$(cat $BATS_TEST_DIRNAME/sampleBranchFilters.txt) SLACK_PARAM_INVERT_MATCH="0" } @@ -151,4 +152,4 @@ setup() { SanitizeVars "$SLACK_PARAM_CUSTOM" printf '%s\n' "Expected: $EXPECTED" "Actual: $CIRCLE_JOB" [ "$CIRCLE_JOB" = "$EXPECTED" ] # Backslashes should be escaped -} \ No newline at end of file +}