"( foo && bar && baz ); finally-code" <- how can finally-code not be run? - node.js

I have this node.js code which generates a bash script:
const k = cp.spawn('bash');
let cmd = [
`cd ${v.path}`,
`git checkout "${releaseName}"`,
`git add .`,
`git commit -am "modified package.json"`,
`git checkout master`,
`( git branch -D -f master_copy_npp_tool &> /dev/null || echo "" ) `,
`git checkout -b master_copy_npp_tool`,
`git merge --no-commit -m "This release branch should be merged into master and integration." "${releaseName}"`,
`git checkout ${releaseName}`,
`git push -u origin ${releaseName}`
]
.join(' && ');
cmd = `( ${cmd} ); git checkout -f master; `; // always checkout the integration branch again, at the end
k.stdin.end(cmd);
For some reason, the script leaves the git repo on the releaseName branch, not master.
The command as a string looks like:
( cd /home/rolo/foo
&& git checkout "oleg/npp_tool/release/1531621240127"
&& git add . && git commit -am "modified package.json"
&& git checkout master
&& ( git branch -D -f master_copy_npp_tool &> /dev/null || echo "" )
&& git checkout -b master_copy_npp_tool
&& git merge --no-commit -m "(shortened)." "oleg/npp_tool/release/1531621240127"
&& git checkout oleg/npp_tool/release/1531621240127
&& git push -u origin oleg/npp_tool/release/1531621240127 );
git checkout -f master;
I am trying to use the last clause:
git checkout -f master;
as a "finally" block. I want to always checkout the master branch in the end no matter way. Anyone know what's going wrong? Like I said it remains on the release branch.
Basically what I tried to do is this pattern:
( foo && bar && star ); finally-clause;

Related

Why do I get this error "git rev-parse --abbrev-ref HEAD was unexpected at this time"?

I have a Node application and I'm running a sonar scan locally by running npm run sonar-scanner. Below is my mackage.json code.
// package.json
...
"scripts": {
"sonar_scanner_branch": "node_modules/sonarqube-scanner/dist/bin/sonar-scanner -Dsonar.branch.name=\"$(git rev-parse --abbrev-ref HEAD)\"",
"sonar_scanner_develop": "node_modules/sonarqube-scanner/dist/bin/sonar-scanner",
"sonar-scanner": "sh updateSonarProps.sh && if [ \"$(git rev-parse --abbrev-ref HEAD)\" = develop ] || [ \"$(git rev-parse --abbrev-ref HEAD)\" = master ] ; then npm run sonar_scanner_develop ; else npm run sonar_scanner_branch ; exit 0 ; fi"
.
.
.
}
This was working fine in my ubuntu 20.0 machine. But it's not working on my windows machine even if I use the same Node version. Below is the error
sh updateSonarProps.sh && if [ "$(git rev-parse --abbrev-ref HEAD)" = develop ] || [ "$(git rev-parse --abbrev-ref HEAD)" = master ] ; then npm run sonar_scanner_develop ; else npm run sonar_scanner_branch ; exit 0 ; fi
"$(git rev-parse --abbrev-ref HEAD)" was unexpected at this time.
What may be the reason for it?

Everything runs fine, but at the end the following error comes

Code:
#!/usr/bin/env bash
# Exit immediately if command returns bad exit code
set -e
ENABLED_SLACK_REFS=(develop qa main prod)
export CI_COMMIT_AUTHOR=$(git log --format="%an" -n1)
export CI_COMMIT_MESSAGE=$(git log --format="%B" -n1)
export CI_COMMIT_URL="${CI_PROJECT_URL}/commit/${CI_COMMIT_SHA}"
main() {
if fn_exists $1; then
${1}
else
echo "Function $1 doesn't exist" && exit 1
fi
}
#------------------------------------------
# Job Tasks
#------------------------------------------
function build_docker_for_pipeline() {
# Pull latest version of image for branch / tag, for caching purposes (speed up the build)
# docker pull ${CI_REGISTRY_IMAGE}:${CI_BRANCH_SLUG} || true
# Build and tag with this pipeline ID so we can use it later, in test & release & deploy
docker build --build-arg CI=${CI} -t ${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID} .
# docker push ${CI_REGISTRY_IMAGE}
}
function lint() {
# docker pull ${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID}
docker run --rm -e CI=${CI} ${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID} lint
}
function test() {
# Pull image built within this pipeline previously
docker pull ${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID}
# Run npm test, via entrypoint.sh test action and generate coverage
mkdir coverage && docker run --rm -e CI=${CI} \
--mount type=bind,source="$(pwd)"/coverage,target=/app/coverage \
${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID} test --coverage
}
function security() {
# Pull image built within this pipeline previously
docker pull ${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID}
# Audit our dependencies for security vulnerabilities
docker run --rm -e CI=${CI} ${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID} yarn audit
}
function release_docker_for_branch() {
# Pull image built in this pipeline
docker pull ${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID}
# Tag as latest image for branch / tag
docker tag ${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID} ${CI_REGISTRY_IMAGE}:${CI_BRANCH_SLUG}
# Push to GitLab Container Registry
docker push ${CI_REGISTRY_IMAGE}
}
function deploy() {
# Run npm build, setting REACT_APP_* env variables
export REACT_APP_ENVIRONMENT=${CI_ENVIRONMENT_NAME:-dev}
export REACT_APP_SENTRY_VERSION="${CI_PROJECT_NAME}#$(jq -r '.version' package.json)-${CI_JOB_ID}"
echo $REACT_APP_SENTRY_VERSION
echo "Building app via Docker, injecting following environment variables:"
get_react_env_vars_raw_names
docker run --rm -v source=/home/halo-solutions-ltd/actions-runner/_work/halo-web/halo-web/,target=/app \
$(get_react_env_vars_for_docker) \
${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID} build
# create_sentry_release
# Set up required environment variables for deployment
export_deploy_ci_variables
aws configure set default.s3.max_concurrent_requests 20
# Sync build output with what is currently deployed
# This also deletes files in bucket that aren't present in build output (cleans old releases)
# Set a blanket cache policy to cache for up to 12hrs - used for versioned static assets
aws s3 sync build s3://${CI_DEPLOY_BUCKET} --delete --cache-control "public,max-age=43200" --exclude "*.map"
# Disable caching for specific files. In particular, ones that reference versioned assets
# This means we can cache bust our versioned assets!
export CACHE_DISABLED_PARAMS="--metadata-directive REPLACE --cache-control max-age=0,no-cache,no-store,must-revalidate --acl public-read"
aws s3 cp s3://${CI_DEPLOY_BUCKET}/service-worker.js s3://${CI_DEPLOY_BUCKET}/service-worker.js --content-type application/javascript ${CACHE_DISABLED_PARAMS}
aws s3 cp s3://${CI_DEPLOY_BUCKET}/index.html s3://${CI_DEPLOY_BUCKET}/index.html --content-type text/html ${CACHE_DISABLED_PARAMS}
aws s3 cp s3://${CI_DEPLOY_BUCKET}/manifest.json s3://${CI_DEPLOY_BUCKET}/manifest.json --content-type application/json ${CACHE_DISABLED_PARAMS}
aws s3 cp s3://${CI_DEPLOY_BUCKET}/asset-manifest.json s3://${CI_DEPLOY_BUCKET}/asset-manifest.json --content-type application/json ${CACHE_DISABLED_PARAMS}
# finalize_sentry_release
}
function deploy_qa_if_updated() {
last_qa_release=$(AWS_DEFAULT_REGION=eu-west-1 AWS_ACCESS_KEY_ID=AKIAJ6355LQD3QU4IK3A AWS_SECRET_ACCESS_KEY=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 \
aws dynamodb get-item --table-name gitlab-react-qa-releases --key "{\"ProjectId\": {\"N\": \"${CI_PROJECT_ID}\"}}" \
--output text --query "Item.[LastReleaseSha.S,LastReleaseTimestamp.N]"
)
echo "Last QA Release: ${last_qa_release}"
# If first QA release
if [ "${last_qa_release}" = "None" ]; then
deploy && update_last_qa_release && deploy_success_slack
return 0
fi
last_qa_release_sha=$(echo "${last_qa_release}" | awk '{print $1}')
last_qa_release_timestamp=$(echo "${last_qa_release}" | awk '{print $2}')
# If current commit is same as last release, or last release isn't in history (not sure how)
if [ "${CI_COMMIT_SHA}" = "${last_qa_release_sha}" ] || ! git merge-base --is-ancestor ${last_qa_release_sha} HEAD; then
no_qa_updates_slack ${last_qa_release_sha} ${last_qa_release_timestamp}
return 0
fi
# If last release occurred previously in branch
deploy && update_last_qa_release && deploy_success_slack
return 0
}
function update_last_qa_release() {
AWS_DEFAULT_REGION=eu-west-1 AWS_ACCESS_KEY_ID=AKIAJ6355LQD3QU4IK3A AWS_SECRET_ACCESS_KEY=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 \
aws dynamodb put-item --table-name gitlab-react-qa-releases --item \
"{\
\"ProjectId\": {\"N\": \"${CI_PROJECT_ID}\"}, \
\"LastReleaseSha\": {\"S\": \"${CI_COMMIT_SHA}\"}, \
\"LastReleaseTimestamp\": {\"N\": \"$(date +%s)\"} \
}"
}
#------------------------------------------
# Slack functions
#------------------------------------------
function slack_enabled_for_ref() {
local ref
ref=${CI_COMMIT_REF_NAME:-none}
echo "${ENABLED_SLACK_REFS[*]}" | grep -F -q -w "$ref";
}
function deploy_success_slack() {
if [ ! -z ${CI_SLACK_WEBHOOK_URL+x} ] && slack_enabled_for_ref; then
local text attachments
export_deploy_ci_variables
text="Successful deployment of <${CI_PIPELINE_URL}|${CI_PROJECT_NAME}> to <${CF_URL}|${CI_ENVIRONMENT_NAME}>"
attachments="{\"fallback\":\"${text}\",\"color\":\"good\", \"text\": \"${text}\",\
\"fields\": [\
{\"title\": \"Git Commit\", \"value\": \"${CI_COMMIT_MESSAGE}\"},\
{\"title\": \"Git Author\", \"value\": \"${CI_COMMIT_AUTHOR}\"}\
],\
\"actions\": [\
{\"type\": \"button\", \"text\": \"View Pipeline\", \"style\": \"primary\", \"url\": \"${CI_PIPELINE_URL}\"}\
]\
}"
curl -s -X POST --data-urlencode \
"payload={\"channel\": \"${CI_SLACK_CHANNEL}\", \"username\": \"React GitLab CICD\",\
\"attachments\": [${attachments}], \"icon_emoji\": \":reactjs:\" }" \
"${CI_SLACK_WEBHOOK_URL}"
fi
}
function deploy_failure_slack() {
if [ ! -z ${CI_SLACK_WEBHOOK_URL+x} ] && slack_enabled_for_ref; then
local text attachments
text="Failed to deploy <${CI_PIPELINE_URL}|${CI_PROJECT_NAME}> to ${CI_ENVIRONMENT_NAME}"
attachments="{\"fallback\":\"${text}\",\"color\":\"danger\", \"text\": \"${text}\",\
\"fields\": [\
{\"title\": \"Git Commit\", \"value\": \"${CI_COMMIT_MESSAGE}\"},\
{\"title\": \"Git Author\", \"value\": \"${CI_COMMIT_AUTHOR}\"}\
],\
\"actions\": [\
{\"type\": \"button\", \"text\": \"View Pipeline\", \"style\": \"primary\", \"url\": \"${CI_PIPELINE_URL}\"}\
]\
}"
curl -s -X POST --data-urlencode \
"payload={\"channel\": \"${CI_SLACK_CHANNEL}\", \"username\": \"React GitLab CICD\",\
\"attachments\": [${attachments}], \"icon_emoji\": \":reactjs:\" }" \
"${CI_SLACK_WEBHOOK_URL}"
fi
}
function job_failure_slack() {
if [ ! -z ${CI_SLACK_WEBHOOK_URL+x} ] && slack_enabled_for_ref; then
local text attachments
text="The ${CI_JOB_NAME} job failed in the <${CI_PIPELINE_URL}|${CI_PROJECT_NAME}> pipeline."
attachments="{\"fallback\":\"${text}\",\"color\":\"danger\", \"text\": \"${text}\",\
\"fields\": [\
{\"title\": \"Git Author\", \"value\": \"${CI_COMMIT_AUTHOR}\", \"short\": true},\
{\"title\": \"Git Branch\", \"value\": \"${CI_COMMIT_REF_NAME}\", \"short\": true}\
],\
\"actions\": [\
{\"type\": \"button\", \"text\": \"View Pipeline\", \"style\": \"primary\", \"url\": \"${CI_PIPELINE_URL}\"}\
]\
}"
curl -s -X POST --data-urlencode \
"payload={\"channel\": \"${CI_SLACK_CHANNEL}\", \"username\": \"React GitLab CICD\",\
\"attachments\": [${attachments}], \"icon_emoji\": \":reactjs:\" }" \
"${CI_SLACK_WEBHOOK_URL}"
fi
}
function no_qa_updates_slack() {
# $1 = Last Release Sha, $2 = Last Release Timestamp
if [ ! -z ${CI_SLACK_WEBHOOK_URL+x} ] && slack_enabled_for_ref; then
local text attachments
text="No unreleased changes found to make a scheduled QA release. The last release was at $(date --date="#$2" "+%a %d %b %T UTC")"
attachments="{\"fallback\":\"${text}\",\"color\":\"good\", \"text\": \"${text}\",\
\"fields\": [\
{\"title\": \"Last Commit Message\", \"value\": \"$(git show -s --format=%B $1)\"},\
{\"title\": \"Last Commit Hash\", \"value\": \"<${CI_PROJECT_URL}/commit/$1|$(git rev-parse --short $1)>\"}\
]\
}"
curl -s -X POST --data-urlencode \
"payload={\"channel\": \"${CI_SLACK_CHANNEL}\", \"username\": \"React GitLab CICD\",\
\"attachments\": [${attachments}], \"icon_emoji\": \":reactjs:\" }" \
"${CI_SLACK_WEBHOOK_URL}"
fi
}
#------------------------------------------
# utils
#------------------------------------------
# Create a Sentry release and upload source maps
function create_sentry_release() {
export SENTRY_URL="${SENTRY_URL:-https://sentry.io}"
export SENTRY_AUTH_TOKEN="${SENTRY_AUTH_TOKEN}"
export SENTRY_ORG="${SENTRY_ORG:-halo-solutions-ltd}"
export SENTRY_PROJECT="${SENTRY_PROJECT:-$CI_PROJECT_NAME}"
export SENTRY_DISABLE_UPDATE_CHECK="true"
export SENTRY_LOG_LEVEL="info"
sentry-cli releases new $REACT_APP_SENTRY_VERSION
#TODO: sentry-cli releases set-commits --auto $REACT_APP_SENTRY_VERSION
sentry-cli releases files $REACT_APP_SENTRY_VERSION upload-sourcemaps -x .js -x .map --validate --rewrite --url-prefix '~/static/js/' ./build/static/js/
}
# Finalize a Sentry release (call once deployed)
function finalize_sentry_release() {
sentry-cli releases finalize $REACT_APP_SENTRY_VERSION
}
# Get the REACT_APP env vars for this build.
# That is, env vars beginning with REACT_APP_ or <ENV>_REACT_APP_
function get_react_env_vars() {
env | egrep "(^REACT_APP_)|(^${CI_ENVIRONMENT_NAME}_REACT_APP_)"
}
# Get the raw names of REACT_APP env vars we will be injecting into build
# That is, names of all env vars starting with REACT_APP_ or <ENV>_REACT_APP_
function get_react_env_vars_raw_names() {
get_react_env_vars | egrep -oh "^(.*=)*" | cut -d '=' -f 1
}
# Get react env vars in format ready to pass to Docker as env variables
# all <ENV>_REACT_APP_ vars renamed to REACT_APP_ format
# Prepended with -e so it can be passed to Docker build as env vars
function get_react_env_vars_for_docker() {
get_react_env_vars | sed "s/^${CI_ENVIRONMENT_NAME}_REACT_APP/REACT_APP/" \
| sed "s/^/-e /"
}
# Export CI variables needed for deployment
function export_deploy_ci_variables() {
export AWS_ACCESS_KEY_ID=$(A=${CI_ENVIRONMENT_NAME}_CI_DEPLOY_ACCESS_KEY_ID; echo ${!A})
export AWS_SECRET_ACCESS_KEY=$(A=${CI_ENVIRONMENT_NAME}_CI_DEPLOY_SECRET_ACCESS_KEY; echo ${!A})
export AWS_DEFAULT_REGION=$(A=${CI_ENVIRONMENT_NAME}_CI_DEPLOY_REGION; echo ${!A})
export CI_DEPLOY_BUCKET=$(S3=${CI_ENVIRONMENT_NAME}_CI_DEPLOY_BUCKET; echo ${!S3})
export CI_CF_DISTRIBUTION=$(CFD=${CI_ENVIRONMENT_NAME}_CI_CF_DISTRIBUTION; echo ${!CFD})
export CF_URL=$(aws cloudfront get-distribution --id ${CI_CF_DISTRIBUTION} \
--query "Distribution.[DomainName, DistributionConfig.Aliases.Items[0]]" \
--output text | awk '{if($2 == "None"){print "http://"$1} else {print "http://"$2}}')
}
function fn_exists() {
# appended double quote is an ugly trick to make sure we do get a string -- if $1 is not a known command, type does not output anything
[ `type -t $1`"" == 'function' ]
}
main "$#"
Now here is the working flow of github:
name: halo solutions web-admin deployment
# Modified for Halo post HHL handover 21/05/22 ML
# develop -> dev
# qa -> qa
# main -> uat
# prod -> prod/live
on:
workflow_dispatch:
push:
branches:
- feature/*
- issue/*
- develop
- qa
- main
- prod
pull_request:
branches:
- develop
- qa
- main
- prod
env:
PROJECT: halo-web
CI_REGISTRY_IMAGE: halo-solutions-ltd/halo-web
CI_ENVIRONMENT_NAME: DEV
CI_SLACK_CHANNEL: ${{ secrets.CI_SLACK_CHANNEL }}
CI_SLACK_WEBHOOK_URL: ${{ secrets.CI_SLACK_WEBHOOK_URL }}
CI_JOB_ID: ${{ github.run_id }}
CI_PIPELINE_ID: ${{ github.run_id }}
jobs:
lint_test_build_release:
runs-on: [ubuntu-latest]
container:
image: ghcr.io/halo-solutions-ltd/docker-aws:latest
steps:
- name: Checkout repo content
uses: actions/checkout#v2
- name: Build
uses: ./.github/common/build
with:
command: "./ci build_docker_for_pipeline || { ./ci job_failure_slack; exit 1; }"
# TODO : Need to implement composite action so we can avoid repeating the code
- name: Dev deploy
if: github.ref == 'refs/heads/develop'
run: |
export CI_COMMIT_REF_NAME=$(echo ${GITHUB_REF#refs/heads/} | sed -e 's/[^A-Za-z0-9._-]/_/g')
export CI_ENVIRONMENT_NAME=DEV
export DEV_REACT_APP_ENV_NAME=${{ secrets.DEV_REACT_APP_ENV_NAME }}
export DEV_REACT_APP_JS_KEY=${{ secrets.DEV_REACT_APP_JS_KEY }}
export DEV_REACT_APP_KEY=${{ secrets.DEV_REACT_APP_KEY }}
export DEV_REACT_APP_PARSE_SERVER=${{ secrets.DEV_REACT_APP_PARSE_SERVER }}
export DEV_REACT_APP_SERVER=${{ secrets.DEV_REACT_APP_SERVER }}
export DEV_CI_DEPLOY_ACCESS_KEY_ID=${{ secrets.DEV_CI_DEPLOY_ACCESS_KEY_ID }}
export DEV_CI_DEPLOY_SECRET_ACCESS_KEY=${{ secrets.DEV_CI_DEPLOY_SECRET_ACCESS_KEY }}
export DEV_CI_DEPLOY_REGION=${{ secrets.DEV_CI_DEPLOY_REGION }}
export DEV_CI_DEPLOY_BUCKET=${{ secrets.DEV_CI_DEPLOY_BUCKET }}
export DEV_CI_CF_DISTRIBUTION=${{ secrets.DEV_CI_CF_DISTRIBUTION }}
./ci deploy && ./ci deploy_success_slack || { ./ci deploy_failure_slack; exit 1; }
- name: QA deploy
if: github.ref == 'refs/heads/qa'
run: |
export CI_COMMIT_REF_NAME=$(echo ${GITHUB_REF#refs/heads/} | sed -e 's/[^A-Za-z0-9._-]/_/g')
export CI_ENVIRONMENT_NAME=QA
export QA_REACT_APP_ENV_NAME=${{ secrets.QA_REACT_APP_ENV_NAME }}
export QA_REACT_APP_JS_KEY=${{ secrets.QA_REACT_APP_JS_KEY }}
export QA_REACT_APP_KEY=${{ secrets.QA_REACT_APP_KEY }}
export QA_REACT_APP_PARSE_SERVER=${{ secrets.QA_REACT_APP_PARSE_SERVER }}
export QA_REACT_APP_SERVER=${{ secrets.QA_REACT_APP_SERVER }}
export QA_CI_DEPLOY_ACCESS_KEY_ID=${{ secrets.QA_CI_DEPLOY_ACCESS_KEY_ID }}
export QA_CI_DEPLOY_SECRET_ACCESS_KEY=${{ secrets.QA_CI_DEPLOY_SECRET_ACCESS_KEY }}
export QA_CI_DEPLOY_REGION=${{ secrets.QA_CI_DEPLOY_REGION }}
export QA_CI_DEPLOY_BUCKET=${{ secrets.QA_CI_DEPLOY_BUCKET }}
export QA_CI_CF_DISTRIBUTION=${{ secrets.QA_CI_CF_DISTRIBUTION }}
./ci deploy && ./ci deploy_success_slack || { ./ci deploy_failure_slack; exit 1; }
- name: UAT deploy
if: github.ref == 'refs/heads/main'
run: |
export CI_COMMIT_REF_NAME=$(echo ${GITHUB_REF#refs/heads/} | sed -e 's/[^A-Za-z0-9._-]/_/g')
export CI_ENVIRONMENT_NAME=UAT
export UAT_REACT_APP_ENV_NAME=${{ secrets.UAT_REACT_APP_ENV_NAME }}
export UAT_REACT_APP_JS_KEY=${{ secrets.UAT_REACT_APP_JS_KEY }}
export UAT_REACT_APP_KEY=${{ secrets.UAT_REACT_APP_KEY }}
export UAT_REACT_APP_PARSE_SERVER=${{ secrets.UAT_REACT_APP_PARSE_SERVER }}
export UAT_REACT_APP_SERVER=${{ secrets.UAT_REACT_APP_SERVER }}
export UAT_CI_DEPLOY_ACCESS_KEY_ID=${{ secrets.UAT_CI_DEPLOY_ACCESS_KEY_ID }}
export UAT_CI_DEPLOY_SECRET_ACCESS_KEY=${{ secrets.UAT_CI_DEPLOY_SECRET_ACCESS_KEY }}
export UAT_CI_DEPLOY_REGION=${{ secrets.UAT_CI_DEPLOY_REGION }}
export UAT_CI_DEPLOY_BUCKET=${{ secrets.UAT_CI_DEPLOY_BUCKET }}
export UAT_CI_CF_DISTRIBUTION=${{ secrets.UAT_CI_CF_DISTRIBUTION }}
./ci deploy && ./ci deploy_success_slack || { ./ci deploy_failure_slack; exit 1; }
- name: LIVE deploy
if: github.ref == 'refs/heads/prod'
run: |
export CI_COMMIT_REF_NAME=$(echo ${GITHUB_REF#refs/heads/} | sed -e 's/[^A-Za-z0-9._-]/_/g')
export CI_ENVIRONMENT_NAME=LIVE
export LIVE_REACT_APP_ENV_NAME=${{ secrets.LIVE_REACT_APP_ENV_NAME }}
export LIVE_REACT_APP_KEY=${{ secrets.LIVE_REACT_APP_KEY }}
export LIVE_REACT_APP_PARSE_SERVER=${{ secrets.LIVE_REACT_APP_PARSE_SERVER }}
export LIVE_REACT_APP_SERVER=${{ secrets.LIVE_REACT_APP_SERVER }}
export LIVE_CI_DEPLOY_ACCESS_KEY_ID=${{ secrets.LIVE_CI_DEPLOY_ACCESS_KEY_ID }}
export LIVE_CI_DEPLOY_SECRET_ACCESS_KEY=${{ secrets.LIVE_CI_DEPLOY_SECRET_ACCESS_KEY }}
export LIVE_CI_DEPLOY_REGION=${{ secrets.LIVE_CI_DEPLOY_REGION }}
export LIVE_CI_DEPLOY_BUCKET=${{ secrets.LIVE_CI_DEPLOY_BUCKET }}
export LIVE_CI_CF_DISTRIBUTION=${{ secrets.LIVE_CI_CF_DISTRIBUTION }}
./ci deploy && ./ci deploy_success_slack || { ./ci deploy_failure_slack; exit 1; }
These are errors:
Done in 86.82s.
The user-provided path build does not exist.
fatal: unsafe repository ('/__w/halo-web/halo-web' is owned by someone else)
To add an exception for this directory, call:
git config --global --add safe.directory /__w/halo-web/halo-web
fatal: unsafe repository ('/__w/halo-web/halo-web' is owned by someone else)
To add an exception for this directory, call:
git config --global --add safe.directory /__w/halo-web/halo-web
Error: Process completed with exit code 3.
This is the thing which is very all ok but providing some type of errors and make some errors. Have any suggestions related to this..?

How to validate the output of grep in Jenkinsfile groovy

I am trying to run a command to retrieve the latest commit message in git and then do a grep to see if it contains certain string and then use that as a condition but getting errors.
def commitmsg = sh(returnStdout: true, script: "git log -1 --pretty='%s' | grep Merge").trim()
if (env.BRANCH_NAME == 'release' && commitmsg == 'Merge')
{
..........
}
How do i get this to work? I just want that if the output of
git log -1 --pretty='%s'
contains the string Merge then i can use it under if condition
I was able to get this to work.
def commitmsg = sh(returnStdout: true, script: "git log -1 --pretty='%s'").trim()
if (env.BRANCH_NAME == 'release' && commitmsg.contains("Merge pull request") == true)
{
....
}

How to fix node.js using sails error: Failed to lift app

I’m trying to deploy a node.js app using the framework Sails in production mode.
I’m using the command npm start which runs NODE_ENV=production node app.js. In package.json I have the following content:
{
"name": "myapp",
"private": true,
"version": "0.0.0",
"description": "a Sails application",
"keywords": [],
"dependencies": {
"sails": "^1.2.3",
"grunt": "1.0.4",
"sails-hook-apianalytics": "^2.0.3",
"sails-hook-grunt": "^3.0.2",
"sails-hook-organics": "^0.16.0",
"sails-hook-orm": "^2.1.1",
"sails-hook-sockets": "^2.0.0",
"#sailshq/connect-redis": "^3.2.1",
"#sailshq/socket.io-redis": "^5.2.0",
"#sailshq/lodash": "^3.10.3"
},
"devDependencies": {
"eslint": "5.16.0",
"htmlhint": "0.11.0",
"lesshint": "6.3.6",
"#sailshq/eslint": "^4.19.3",
"sails-hook-grunt": "^4.0.0"
},
"scripts": {
"start": "NODE_ENV=production node app.js",
"test": "npm run lint && npm run custom-tests && echo 'Done.'",
"lint": "./node_modules/eslint/bin/eslint.js . --max-warnings=0 --report-unused-disable-directives && echo '✔ Your .js files look so good.' && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/**/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/**/**/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/**/**/**/**/*.ejs && echo '✔ So do your .ejs files.' && ./node_modules/lesshint/bin/lesshint assets/styles/ --max-warnings=0 && echo '✔ Your .less files look good, too.'",
"custom-tests": "echo \"(No other custom tests yet.)\" && echo",
"deploy": "echo 'This script assumes a dead-simple, opinionated setup on Heroku.' && echo 'But, of course, you can deploy your app anywhere you like.' && echo '(Node.js/Sails.js apps are supported on all modern hosting platforms.)' && echo && echo 'Warning: Specifically, this script assumes you are on the master branch, and that your app can be deployed simply by force-pushing on top of the *deploy* branch. It will also temporarily use a local *predeploy* branch for preparing assets, that it will delete after it finishes. Please make sure there is nothing you care about on either of these two branches!!!' && echo '' && echo '' && echo 'Preparing to deploy...' && echo '--' && git status && echo '' && echo '--' && echo 'I hope you are on the master branch and have everything committed/pulled/pushed and are completely up to date and stuff.' && echo '********************************************' && echo '** IF NOT THEN PLEASE PRESS <CTRL+C> NOW! **' && echo '********************************************' && echo 'Press CTRL+C to cancel.' && echo '(you have five seconds)' && sleep 1 && echo '...4' && sleep 1 && echo '...3' && sleep 1 && echo '...2' && sleep 1 && echo '...1' && sleep 1 && echo '' && echo 'Alright, here we go. No turning back now!' && echo 'Trying to switch to master branch...' && git checkout master && echo && echo 'OK. Now wiping node_modules/ and running npm install...' && rm -rf node_modules && rm -rf package-lock.json && npm install && (git add package-lock.json && git commit -am 'AUTOMATED COMMIT: Did fresh npm install before deploying, and it caused something relevant (probably the package-lock.json file) to change! This commit tracks that change.' || true) && echo 'Deploying as version:' && npm version patch && echo '' && git push origin master && git push --tags && (git branch -D predeploy > /dev/null 2>&1 || true) && git checkout -b predeploy && (echo 'Now building+minifying assets for production...' && echo '(Hang tight, this could take a while.)' && echo && node node_modules/grunt/bin/grunt buildProd || (echo && echo '------------------------------------------' && echo 'IMPORTANT! IMPORTANT! IMPORTANT!' && echo 'ERROR: Could not compile assets for production!' && echo && echo 'Attempting to recover automatically by stashing, ' && echo 'switching back to the master branch, and then ' && echo 'deleting the predeploy branch... ' && echo && echo 'After this, please fix the issues logged above' && echo 'and push that up. Then, try deploying again.' && echo '------------------------------------------' && echo && echo 'Staging, deleting the predeploy branch, and switching back to master...' && git stash && git checkout master && git branch -D predeploy && false)) && mv www .www && git add .www && node -e 'sailsrc = JSON.parse(require(\"fs\").readFileSync(\"./.sailsrc\", \"utf8\")); if (sailsrc.paths&&sailsrc.paths.public !== undefined || sailsrc.hooks&&sailsrc.hooks.grunt !== undefined) { throw new Error(\"Cannot complete deployment script: .sailsrc file has conflicting contents! Please throw away this midway-complete deployment, switch back to your original branch (master), remove the conflicting stuff from .sailsrc, then commit and push that up.\"); } sailsrc.paths = sailsrc.paths || {}; sailsrc.paths.public = \"./.www\"; sailsrc.hooks = sailsrc.hooks || {}; sailsrc.hooks.grunt = false; require(\"fs\").writeFileSync(\"./.sailsrc\", JSON.stringify(sailsrc))' && git commit -am 'AUTOMATED COMMIT: Automatically bundling compiled assets as part of deploy, updating the EJS layout and .sailsrc file accordingly.' && git push origin predeploy && git checkout master && git push origin +predeploy:deploy && git push --tags && git branch -D predeploy && git push origin :predeploy && echo '' && echo '--' && echo 'OK, done. It should be live momentarily on your staging environment.' && echo '(if you get impatient, check the Heroku dashboard for status)' && echo && echo 'Staging environment:' && echo ' 🌐–• https://staging.example.com' && echo ' (hold ⌘ and click to open links in the terminal)' && echo && echo 'Please review that to make sure it looks good.' && echo 'When you are ready to go to production, visit your pipeline on Heroku and press the PROMOTE TO PRODUCTION button.'"
},
"main": "app.js",
"repository": {
"type": "git",
"url": "git://github.com/xxxxxx.git"
},
"author": "me",
"license": "",
"engines": {
"node": "^10.16"
}
}
If I run sails lift all gone right.
And when run npm start I get following error:
error: Failed to lift app: Error: Should not specify a trailing slash, but instead got: https://myapp.herokuapp.com/
at checkOriginUrl (/home/me/Documents/prog/myapp/node_modules/sails-hook-sockets/lib/util/check-origin-url.js:57:40)
at /home/me/Documents/prog/myapp/node_modules/sails-hook-sockets/lib/configure.js:86:9
at arrayEach (/home/me/Documents/prog/myapp/node_modules/#sailshq/lodash/lib/index.js:1470:13)
at Function.<anonymous> (/home/me/Documents/prog/myapp/node_modules/#sailshq/lodash/lib/index.js:3532:13)
at Hook.configure (/home/me/Documents/prog/myapp/node_modules/sails-hook-sockets/lib/configure.js:85:9)
at Hook.wrapper [as configure] (/home/me/Documents/prog/myapp/node_modules/#sailshq/lodash/lib/index.js:3282:19)
at /home/me/Documents/prog/myapp/node_modules/sails/lib/app/private/loadHooks.js:331:20
at /home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:3083:16
at eachOfArrayLike (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:1003:9)
at eachOf (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:1051:5)
at Object.eachLimit (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:3145:5)
at configure (/home/me/Documents/prog/myapp/node_modules/sails/lib/app/private/loadHooks.js:328:17)
at /home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:3853:24
at replenish (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:946:17)
at iterateeCallback (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:931:17)
at /home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:906:16
I’m trying to use heroku to deploy the app. For this reason I added this in production.js inside sockets object:
onlyAllowOrigins:[
'https://myapp.herokuapp.com/',
],
I think this problem could be caused by any missed configuration in production.js but I couldn’t identify what.

Only build projects if something has changed

We want to split up our project into smaller pieces. Our current CI process goes through a short test phase and then runs a deployment script. However, if nothing has changed in one of the sub project, we do not want to go through the build for this.
Jenkins without pipelines supports exclusions in the SCM configuration (we use git) and based on this, you can configure a specific job to run. However, when using a pipeline, how can I know, if I should build this part or not? How do I get access to the paths that were affected by the last push?
At the moment our script is very simple, and we would like to keep it as simple as possible.
We were playing around with the scripted and the declarative syntax, but could not find a good solution.
Declarative:
#!groovy​
pipeline {
agent any
tools {
nodejs '8.1'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
# Only continue, if something has changed
stage('Install') {
steps {
sh 'npm install'
}
}
stage('Test') {
steps {
sh 'npm run test-jenkins'
}
post {
always {
junit "artifacts/test/report.xml"
}
}
}
}
}
Scripted:
#!groovy​
node {
def nodejs = tool name: '8.1', type: 'jenkins.plugins.nodejs.tools.NodeJSInstallation'
env.PATH = "${nodejs}/bin:${env.PATH}"
stage('Checkout') {
checkout scm
}
# Only continue, if something has changed
stage('Install') {
sh 'npm install'
}
stage('Test') {
try {
sh 'npm run test-jenkins'
} finally {
junit "artifacts/test/report.xml"
}
}
}
Thanks to ElpieKay's fast comment on my question, we now have an elegant solution:
Make a tag to the current commit on a successful build
In the next build compare the new commit and the tag for changes
We are using a multi-branch pipeline and a parallel build for the multiple projects we have under the same source root. We iterate through the projects (serviceX) and check in the corresponding directory for a change:
def projects = ['service1', 'service2']
def builders = [:]
for (p in projects) {
def label = p
builders[label] = {
def tag = "${BRANCH_NAME}_last"
node {
echo "Checking for changes compared to ${tag} in directory ${label}"
try {
sh "./check-for-changes ${tag} ${label}"
} catch (ignored) {
echo "Nothing to do"
return
}
dir (label) {
stage(label + ": Install") {
sh "npm install"
}
stage(label + ": Test") {
try {
sh "npm run test-jenkins"
} finally {
junit 'artifacts/test/report.xml'
}
}
echo "Setting tag for the last build on this branch"
sh "git tag -f ${tag}"
}
}
}
}
parallel builders
... and the script to check for changes:
#!/bin/bash
SHA_PREV=$1
if [ -z ${SHA_PREV} ]; then
echo "Usage: `basename $0` <tag> <path>"
exit 1
fi
CHECK_PATH=$2
if [ -z ${CHECK_PATH} ]; then
echo "Usage: `basename $0` <tag> <path>"
exit 1
fi
if `git rev-parse ${SHA_PREV} >/dev/null 2>&1`; then
echo "Found previous tag: ${SHA_PREV}"
else
SHA_PREV=`git rev-list --max-parents=0 HEAD`
echo "Using initial commit: ${SHA_PREV}"
fi
changes=`git diff --name-only ${SHA_PREV} HEAD | grep ${CHECK_PATH}/`
if [ ! -n "${changes}" ]; then
echo "No changes found"
exit 2 # no changes found
fi

Resources