Orb version: circleci/slack@3.4.2
Error message: failed to start cmd: exec: "/bin/bash": file does not exist
Orb version: circleci/slack@3.4.2
Error message: failed to start cmd: exec: "/bin/bash": file does not exist
Is it possible to workaround this issue using artifacts and sending all Slack notifications from a docker image?
You can indeed use build artifacts to pass the outcome of a job from a Windows workflow to a Linux workflow and then trick the Slack orb into reporting the status of the Windows workflow from the Linux workflow by overriding the environment variables it reads from. This is a very ugly solution, but I personally prefer it to having no Slack notifications at all on Windows. Another option would be to ditch the Slack orb altogether and hit the Slack API directly. Any feedback folks have on improving this workaround is quite welcome.
version: 2.1
orbs:
slack: circleci/slack@4.4.2
windows: circleci/windows@2.4.0
jobs:
build:
executor: windows/default
steps:
- run:
name: Make directory for job metadata.
command: mkdir C:/tmp/job_metadata
shell: bash.exe
- run:
name: Write current job URL.
command: echo "$CIRCLE_BUILD_URL" > C:/tmp/job_metadata/build_url.txt
shell: bash.exe
...
- run:
when: on_fail
name: Write job exit code 1 for failure.
command: echo 1 > C:/tmp/job_metadata/exit_code.txt
shell: bash.exe
- run:
when: on_success
name: Write job exit code 0 for success.
command: echo 0 > C:/tmp/job_metadata/exit_code.txt
shell: bash.exe
- store_artifacts:
path: /tmp/job_metadata
destination: build-job-metadata
notify:
docker:
- image: cimg/base:stable
resource_class: small
steps:
- run:
name: Download any job metadata artifacts for latest completed job on this branch.
command: >
curl
--header "Content-Type: application/json"
--header "Accept: application/json"
--header "Circle-Token: $CIRCLE_TOKEN"
"https://circleci.com/api/v1.1/project/<< pipeline.project.type >>/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/latest/artifacts?branch=$CIRCLE_BRANCH&filter=completed" |
grep --only-matching 'https://[^"]*build-job-metadata[^"]*' |
xargs -I url wget --header "Circle-Token: $CIRCLE_TOKEN" url
- run:
name: Overwrite CIRCLE_JOB environment variable with build.
command: echo export CIRCLE_JOB=build >> $BASH_ENV
- run:
name: Overwrite CIRCLE_BUILD_URL environment variable from prior job metadata.
command: echo export CIRCLE_BUILD_URL=$(<build_url.txt) >> $BASH_ENV
- run:
name: Exit with code from prior job metadata.
command: exit $(<exit_code.txt)
- slack/notify:
event: fail
template: basic_fail_1
- slack/notify:
event: pass
template: basic_success_1
workflows:
build:
jobs:
- build
# Take advantage of the fact that free CircleCI accounts are limited to
# running one workflow at a time. If you are on a paid account, these
# workflows will instead run in parallel. Consider submitting a pull request
# to the Slack orb to use the bash.exe shell on Windows, using
# https://github.com/eddiewebb/circleci-queue, or using the CircleCI API to
# wait for the build workflow to complete.
notify:
jobs:
- notify:
context:
# a context that defines the CIRCLE_TOKEN environment variable
# to be a CircleCI API token for your project with Admin scope
- circleci-api-admin
# a context that defines the SLACK_ACCESS_TOKEN and SLACK_DEFAULT_CHANNEL
# environment variables as specified by
# https://github.com/CircleCI-Public/slack-orb#readme
- slack
It turns out the use of artifacts is unnecessary, and it’s risky to assume that the most recent completed job on the same branch is the correct job to report the status of. A better solution is to search for the most recent completed job with the same commit hash using the CircleCI API. This also enables propagation of cancellations to the notify job. Put the following code in .circleci/trickSlackOrb.sh:
#!/bin/bash
set -eufo pipefail
# Issues a v1.1 CircleCI API request to the given relative path within this
# project, and outputs the JSON response to stdout. Specify the HTTP request
# method as the second argument. CIRCLE_TOKEN is not a CircleCI built-in and
# must be provided by a context. It must be a CircleCI API token with access to
# this project and the required scope. The environment variable VCS_TYPE is not
# a CircleCI built-in and should be set from the CircleCI config.yml file to
# << pipeline.project.type >>. See
# https://circleci.com/docs/2.0/pipeline-variables/#pipeline-values.
makeApiRequest() {
curl \
--request "$2" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--header "Circle-Token: $CIRCLE_TOKEN" \
"https://circleci.com/api/v1.1/project/$VCS_TYPE/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/$1"
}
# Output the value of the given JSON key to stdout. The second parameter is the
# JSON string to search.
getJsonValue() {
local match="$(grep --only-matching "\"$1\"\s*:\s*\"[^\"]*\"" <<< "$2")"
# Get the value between the third and fourth double quotes.
cut --delimiter=\" --fields=4 <<< "$match"
}
# Trick the Slack orb into reporting the status of the most recently completed
# job preceding this one that has the same VCS commit hash. Fail this job if the
# preceding one failed. Cancel this job if the preceding one was cancelled.
# Overwrite the CIRCLE_JOB environment variable with the prior job's name and
# the CIRCLE_BUILD_URL environment variable with the prior job's URL. The other
# CIRCLE_* environment variables that Slack reads from should be the same
# between this notify job and the corresponding prior job. If no corresponding
# job can be found, fail this job without tricking Slack.
trickSlackOrb() {
local buildNum
for ((buildNum = $CIRCLE_BUILD_NUM - 1; buildNum > 0; buildNum--))
do
# This API request requires that CIRCLE_TOKEN have at least the read only
# scope. See https://circleci.com/docs/api/v1/#single-job.
local jobMetadata="$(makeApiRequest "$buildNum" "GET")"
local job="$(getJsonValue "CIRCLE_JOB" "$jobMetadata")"
if [[ "$job" != "notify" ]] &&
grep --quiet "\"vcs_revision\":\"$CIRCLE_SHA1\"" <<< "$jobMetadata" &&
grep --quiet '"lifecycle":"finished"' <<< "$jobMetadata" &&
grep --quiet '"dont_build":null' <<< "$jobMetadata"
then
if grep --quiet '"outcome":"canceled"' <<< "$jobMetadata"
then
# Cancels the currently executing CircleCI job, and outputs a JSON document
# containing metadata regarding this job to stdout. See
# https://circleci.com/docs/api/v1/#cancel-a-build. This API request
# requires that CIRCLE_TOKEN token have the admin scope.
makeApiRequest "$CIRCLE_BUILD_NUM/cancel" "POST"
# Give the cancellation up to a minute to take effect before failing.
sleep 60
break
fi
local buildUrl="$(getJsonValue "build_url" "$jobMetadata")"
echo "export CIRCLE_JOB=$job" >> $BASH_ENV
echo "export CIRCLE_BUILD_URL=$buildUrl" >> $BASH_ENV
grep --quiet '"outcome":"success"' <<< "$jobMetadata" && return
break
fi
done
exit 1
}
trickSlackOrb
Include an extra job in your .circleci/config.yml that runs the script and issues the Slack notification:
version: 2.1
orbs:
slack: circleci/slack@4.4.2
windows: circleci/windows@2.4.0
jobs:
build:
executor: windows/default
steps:
...
notify:
docker:
- image: cimg/base:stable
resource_class: small
steps:
- checkout
- run:
name: Trick the Slack orb into reporting the status of the most recently finished preceding build job.
command: source .circleci/trickSlackOrb.sh
environment:
VCS_TYPE: << pipeline.project.type >>
- slack/notify:
event: fail
template: basic_fail_1
- slack/notify:
event: pass
template: basic_success_1
workflows:
build:
jobs:
- build
# Take advantage of the fact that free CircleCI accounts are limited to
# running one workflow at a time. If you are on a paid account, these
# workflows will instead run in parallel. Consider submitting a pull request
# to the Slack orb to use the bash.exe shell on Windows, using
# https://github.com/eddiewebb/circleci-queue, or using the CircleCI API to
# wait for the build workflow to complete.
notify:
jobs:
- notify:
context:
# a context that defines the CIRCLE_TOKEN environment variable
# to be a CircleCI API token for your project with Admin scope
- circleci-api-admin
# a context that defines the SLACK_ACCESS_TOKEN and SLACK_DEFAULT_CHANNEL
# environment variables as specified by
# https://github.com/CircleCI-Public/slack-orb#readme
- slack
Hey folks
Window support was implemented on v4.12.0. As long as your executor’s shell is bash.exe
, it should work out of the box without any additional configuration.