Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

agri nmp new bcdk pipeline changes #407

Merged
merged 2 commits into from
Nov 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
* text eol=lf
*.[bB][aA][tT] text eol=crlf
*.[cC][mM][dD] text eol=crlf
*.[pP][sS][1] text eol=crlf
*.[pP][nN][gG] binary
*.[tT][tT][fF] binary
*.[eE][oO][tT] binary
*.[jJ][pP][gG] binary
*.[jJ][pP][eE][gG] binary
*.[dD][bB] binary
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,4 @@ functional-tests/build/*

#MacOS stuff
.DS_Store
node_modules/
1 change: 1 addition & 0 deletions .jenkins/.pipeline/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v10.15.2
5 changes: 5 additions & 0 deletions .jenkins/.pipeline/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';
const task = require('./lib/build.js')
const settings = require('./lib/config.js')

task(Object.assign(settings, { phase: 'build'}))
5 changes: 5 additions & 0 deletions .jenkins/.pipeline/clean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';
const settings = require('./lib/config.js')
const task = require('./lib/clean.js')

task(Object.assign(settings, { phase: settings.options.env}));
5 changes: 5 additions & 0 deletions .jenkins/.pipeline/deploy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';
const settings = require('./lib/config.js')
const task = require('./lib/deploy.js')

task(Object.assign(settings, { phase: settings.options.env}));
36 changes: 36 additions & 0 deletions .jenkins/.pipeline/lib/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';
const {OpenShiftClientX} = require('pipeline-cli')
const path = require('path');

module.exports = (settings)=>{
const phases=settings.phases
const options = settings.options
const oc=new OpenShiftClientX(Object.assign({'namespace':phases.build.namespace}, options));
const phase='build'
var objects = []

const templatesLocalBaseUrl =oc.toFileUrl(path.resolve(__dirname, '../../openshift'))

objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/build-master.yaml`, {
'param':{
'NAME': phases[phase].name,
'SUFFIX': phases[phase].suffix,
'VERSION': phases[phase].tag,
'SOURCE_REPOSITORY_URL': oc.git.http_url,
'SOURCE_REPOSITORY_REF': oc.git.ref
}
}));

objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/build-slave.yaml`, {
'param':{
'NAME': phases[phase].name,
'SUFFIX': phases[phase].suffix,
'VERSION': phases[phase].tag,
'SOURCE_IMAGE_STREAM_TAG': `${phases[phase].name}:${phases[phase].tag}`,
'SLAVE_NAME':'main'
}
}));

oc.applyRecommendedLabels(objects, phases[phase].name, phase, phases[phase].changeId, phases[phase].instance)
oc.applyAndBuild(objects)
}
37 changes: 37 additions & 0 deletions .jenkins/.pipeline/lib/clean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';
const {OpenShiftClientX} = require('pipeline-cli')

module.exports = (settings)=>{
const phases = settings.phases
const options = settings.options
const oc=new OpenShiftClientX(Object.assign({'namespace':phases.build.namespace}, options));
const target_phase=options.env

for (var k in phases){
if (phases.hasOwnProperty(k)) {
const phase=phases[k]
if (k == target_phase ){
//console.log(`phase=${phase}`)
//oc.raw('get', ['bc'], {selector:`app-name=${phase.name},env-id=${phase.changeId},env-name!=prod,!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, namespace:phase.namespace, 'output':'custom-columns=kind:.spec.output.to.kind,name:.spec.output.to.name', 'no-headers':'true'})
let buildConfigs=oc.get('bc', {selector:`app=${phase.instance},env-id=${phase.changeId},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, namespace:phase.namespace})
buildConfigs.forEach((bc)=>{
if (bc.spec.output.to.kind == 'ImageStreamTag'){
oc.delete([`ImageStreamTag/${bc.spec.output.to.name}`],{'ignore-not-found':'true', 'wait':'true', namespace:phase.namespace})
}
})

let deploymentConfigs=oc.get('dc', {selector:`app=${phase.instance},env-id=${phase.changeId},env-name=${k},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, namespace:phase.namespace})
deploymentConfigs.forEach((dc)=>{
dc.spec.triggers.forEach((trigger)=>{
if (trigger.type == 'ImageChange' && trigger.imageChangeParams.from.kind == 'ImageStreamTag'){
oc.delete([`ImageStreamTag/${trigger.imageChangeParams.from.name}`],{'ignore-not-found':'true', 'wait':'true', namespace:phase.namespace})
}
})
})

oc.raw('delete', ['all'], {selector:`app=${phase.instance},env-id=${phase.changeId},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, wait:'true', namespace:phase.namespace})
oc.raw('delete', ['pvc,Secret,configmap,endpoints,RoleBinding,role,ServiceAccount,Endpoints'], {selector:`app=${phase.instance},env-id=${phase.changeId},!shared,github-repo=${oc.git.repository},github-owner=${oc.git.owner}`, wait:'true', namespace:phase.namespace})
}
}
}
}
19 changes: 19 additions & 0 deletions .jenkins/.pipeline/lib/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';
const options= require('pipeline-cli').Util.parseArguments()
const changeId = options.pr //aka pull-request
const version = '1.0.0'
const name = 'nmp-jenkins'

const phases = {
build: {namespace:'agri-nmp-tools' , name: `${name}`, phase: 'build' , changeId:changeId, suffix: `-build-${changeId}` , instance: `${name}-build-${changeId}` , version:`${version}-${changeId}`, tag:`build-${version}-${changeId}`},
dev: {namespace:'agri-nmp-tools' , name: `${name}`, phase: 'dev' , changeId:changeId, suffix: `-dev-${changeId}` , instance: `${name}-dev-${changeId}` , version:`${version}-${changeId}`, tag:`dev-${version}-${changeId}`},
prod: {namespace:'agri-nmp-tools' , name: `${name}`, phase: 'prod' , changeId:changeId, suffix: `` , instance: `${name}` , version:`${version}`, tag:`prod-${version}`},
};

// This callback forces the node process to exit as failure.
process.on('unhandledRejection', (reason) => {
console.log(reason);
process.exit(1);
});

module.exports = exports = {phases, options};
44 changes: 44 additions & 0 deletions .jenkins/.pipeline/lib/deploy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict';
const {OpenShiftClientX} = require('pipeline-cli')
const path = require('path');

module.exports = (settings)=>{
const phases = settings.phases
const options = settings.options
const phase=options.env
const changeId = phases[phase].changeId
const oc=new OpenShiftClientX(Object.assign({'namespace':phases[phase].namespace}, options));
var objects = []

const templatesLocalBaseUrl =oc.toFileUrl(path.resolve(__dirname, '../../openshift'))

objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/deploy-master.yaml`, {
'param':{
'NAME': phases[phase].name,
'SUFFIX': phases[phase].suffix,
'VERSION': phases[phase].tag,
'ENV_NAME': phases[phase].phase,
'ROUTE_HOST': `${phases[phase].name}${phases[phase].suffix}-${phases[phase].namespace}.pathfinder.gov.bc.ca`
}
}))

objects.push(...oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/deploy-slave.yaml`, {
'param':{
'NAME': phases[phase].name,
'SUFFIX': phases[phase].suffix,
'VERSION': phases[phase].tag,
'SLAVE_NAME': 'build',
'SLAVE_LABELS': 'build deploy test ui-test',
'SLAVE_EXECUTORS': '3',
'CPU_REQUEST': '300m',
'CPU_LIMIT': '500m',
'MEMORY_REQUEST': '2Gi',
'MEMORY_LIMIT': '2Gi'
}
}))

oc.applyRecommendedLabels(objects, phases[phase].name, phase, `${changeId}`, phases[phase].instance)
oc.importImageStreams(objects, phases[phase].tag, phases.build.namespace, phases.build.tag)
oc.applyAndDeploy(objects, phases[phase].instance)

}
12 changes: 12 additions & 0 deletions .jenkins/.pipeline/npmw
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh
set +x
type -t nvm && nvm deactivate
export NVM_DIR="$(git rev-parse --show-toplevel)/.nvm"
if [ ! -f "$NVM_DIR/nvm.sh" ]; then
mkdir -p "${NVM_DIR}"
curl -sSL -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash &>/dev/null
fi
source "$NVM_DIR/nvm.sh" &>/dev/null
METHOD=script nvm install --no-progress &>/dev/null
nvm use &>/dev/null
exec npm "$@"
46 changes: 46 additions & 0 deletions .jenkins/.pipeline/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions .jenkins/.pipeline/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "pipeline",
"version": "1.0.0",
"description": "This a pipeliene script",
"engines": {
"node": ">=8"
},
"scripts": {
"build": "node build.js",
"clean": "node clean.js",
"deploy": "node deploy.js",
"version": "echo \"node@$(node --version) ($(which node))\" && echo \"npm@$(npm --version) ($(which npm))\" && npm ls"
},
"repository": {
"type": "git",
"url": "git+https://github.com/bcgov/ocp-sso.git"
},
"author": "",
"license": "Apache-2.0",
"dependencies": {
"pipeline-cli": "git+https://github.com/BCDevOps/pipeline-cli.git#v1.1"
}
}
57 changes: 57 additions & 0 deletions .jenkins/Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
pipeline {
agent none
options {
disableResume()
}
stages {
stage('Build') {
agent { label 'build' }
steps {
script {
def filesInThisCommitAsString = sh(script:"git diff --name-only HEAD~1..HEAD | grep '^.jenkins/' || echo -n ''", returnStatus: false, returnStdout: true).trim()
def hasChangesInPath = (filesInThisCommitAsString.length() > 0)
echo "${filesInThisCommitAsString}"
if (!currentBuild.rawBuild.getCauses()[0].toString().contains('UserIdCause') && !hasChangesInPath){
currentBuild.rawBuild.delete()
error("No changes detected in the path ('^.jenkins/')")
}
}
echo "Aborting all running jobs ..."
script {
abortAllPreviousBuildInProgress(currentBuild)
}
echo "BRANCH_NAME:${env.BRANCH_NAME}\nCHANGE_ID:${env.CHANGE_ID}\nCHANGE_TARGET:${env.CHANGE_TARGET}"
echo "Building ..."
sh "cd .jenkins/.pipeline && ./npmw ci && ./npmw run build -- --pr=${CHANGE_ID}"
}
}
stage('Deploy (DEV)') {
agent { label 'deploy' }
steps {
echo "Deploying ..."
sh "cd .jenkins/.pipeline && ./npmw ci && DEBUG=info* ./npmw run deploy -- --pr=${CHANGE_ID} --env=dev"
}
}
stage('Deploy (PROD)') {
agent { label 'deploy' }
input {
message "Should we continue with deployment to PROD?"
ok "Yes!"
}
steps {
echo "Deploying ..."
sh "cd .jenkins/.pipeline && ./npmw ci && ./npmw run deploy -- --pr=${CHANGE_ID} --env=prod"
}
}
stage('Acceptance') {
agent { label 'deploy' }
input {
message "Should we continue with cleanup?"
ok "Yes!"
}
steps {
echo "Cleaning ..."
}
}
}
}
40 changes: 40 additions & 0 deletions .jenkins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Overview

For running locally, it is recommended to use locally installed npm/node. The command snippets provide bellow assume you have npm/node installed. Also, the command lines are provided as subshell (within parthnesis) so that it will work regardless of of your current shell work directory, as long as it is within the git working directory.

For running from a Jenkinsfile, it is recommened to replace `npm` with the provided `npmw` as it will download and install node/npm using `nvm`.

Before running in any of your projects ensure that you have created proper GitHub and Slave User secrets below:
template.<Your Jenkins>-github
template.<Your Jenkins>-slave-user

Github Webhooks are only created during the PROD deployment.

Windows users can just do the `cd` manually to the root folder of their repo and remove `$(git rev-parse --show-toplevel)/` from the commands below.

# Build
```
( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run build -- --pr=0 --dev-mode=true )
```
Where:
`--pr=0` is used to set the pull request number to build from.
`--dev-mode=true` is used to indicate that the build will actually take the files in the current working directory, as opposed to a fresh `git clone`

# Deploy to DEV
```
( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run deploy -- --pr=0 --env=dev )
```

# Deploy to PROD
```
( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run deploy -- --pr=0 --env=prod )
```

# Clean
The clean script can run against each persistent environment, starting from `build`.
```
( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run clean -- --pr=0 --env=build )
( cd "$(git rev-parse --show-toplevel)/.jenkins/.pipeline" && npm run clean -- --pr=0 --env=dev )
```

*Warning*: Do *NOT* run against `test` or `prod`. It will cause *PERMANENT* deletion of all objects including `PVC`! be warned!
11 changes: 11 additions & 0 deletions .jenkins/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM jenkins/core/there

USER 0
COPY ./contrib/jenkins/configuration $JENKINS_REF_HOME

RUN set -x && \
chgrp -R 0 $JENKINS_REF_HOME && \
chmod -R 644 $JENKINS_REF_HOME && \
chmod -R g+rwX $JENKINS_REF_HOME

USER 1001
Loading