Git Product home page Git Product logo

webapplication's Introduction

Jenkins CI with declarative pipelines

Sample Application for CI/CD using Jenkins with declarative Pipelines as Continuous Integration server.

Jenkins Pipeline

Jenkins Pipeline Stages in Blue Ocean

Diagram

CI Diagram

Tools:

Area Tools
CI Jenkins
Source Code GitHub (Cloud)
Issue Management GitHub (Cloud)
Tech stack ASP.Net MVC, EF, JQuery, Bootstrap, Webpack
Database SQL Server
Web Server IIS
Testing MSTest, Specflow, Selenium, Moq
Build Tools MSBuild, MSDeploy
Dependencies Nuget, npm

Setup

Jenkins

Plugins:

  • github
  • git
  • global-slack-notifier
  • pollscm
  • timestamper
  • mstest
  • msbuild
  • nodejs
  • vstestrunner
  • workflow-aggregator

Config File Management

Added web.config files for Dev, QA and Prod.

Config files

Gihub

Need to add a webhook that points to the Jenkins server.

Github webhooks setup

Github webhooks setup

jenkinsfile:

Environment section

Sets RELEASE_VERSION and tools paths.

environment{
    RELEASE_VERSION = "1.0.1"
    VSTest = tool 'vstest'	
    MSBuild = tool 'msbuild'
    Nuget = 'C:\\Program Files (x86)\\Jenkins\\nuget.exe'
    MSDeploy = "C:\\Program Files (x86)\\IIS\\Microsoft Web Deploy V3\\msdeploy.exe"
}

Stage Get Source

Gets source code and notifies to Slack and Github.

stage('Get Source'){
  steps{
    slackSend (color: '#FFFF00', message: "STARTED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
    setBuildStatus("PENDING: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})", "PENDING");
    checkout([$class: 'GitSCM', branches: [[name: 'master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'github', url: 'https://github.com/alanmacgowan/WebApplication.git']]])
  }
}

Github Pending Status

Github Pending status

Stage Restore dependencies

This stage runs 3 parallel stages: Nuget Restore, NodeJS and Set Assembly Version.

Nuget

Restores nuget packages, runs in parallel.

stage('Restore'){
    steps{
        bat "\"${Nuget}\" restore WebApplication.sln"
    }
}

Stage NodeJS

Installs npm dependencies and runs webpack, runs in parallel.

stage('NodeJS'){
    steps{
        nodejs(nodeJSInstallationName: 'Node') {
            dir('WebApplication')
            {
                bat 'npm install && npm run build:prod'
            }
        }
    }
}	

Stage Set Assembly Version

Changes Assemblyversion number with current Build number, using Powershell script, runs in parallel.

stage('Set Assembly Version') {
  steps {
        dir('WebApplication\\Properties')
        {
            setAssemblyVersion()
        }
   }
}
...
void setAssemblyVersion(){
	powershell ("""
	  \$PatternVersion = '\\[assembly: AssemblyVersion\\("(.*)"\\)\\]'
	  \$AssemblyFiles = Get-ChildItem . AssemblyInfo.cs -rec

	  Foreach (\$File in \$AssemblyFiles)
	  {
		(Get-Content \$File.PSPath) | ForEach-Object{
			If(\$_ -match \$PatternVersion){
				'[assembly: AssemblyVersion("{0}")]' -f "$RELEASE_VERSION.$BUILD_NUMBER"
			} Else {
				\$_
			}
		} | Set-Content \$file.PSPath
	  }
    """)
}

Version

Version number shown in footer

Stage Build & Package

Build and packages WebApplication for latter deployment. The artifact is saved as part of the build in Jenkins.

stage('Build & Package') {
    steps {
	bat "\"${MSBuild}\" WebApplication.sln /p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /t:build /p:Configuration=QA /p:Platform=\"Any CPU\" /p:DesktopBuildPackageLocation=\"%WORKSPACE%\\artifacts\\WebApp_${env.RELEASE_VERSION}.${env.BUILD_NUMBER}.zip\""
    }
}

Stage Unit test

Runs unit tests.

stage('Unit test') {
    steps {
        dir('WebApplication.Tests.Unit\\bin\\Release')
        {
            bat "\"${VSTest}\" \"WebApplication.Tests.Unit.dll\" /Logger:trx;LogFileName=Results_${env.BUILD_NUMBER}.trx /Framework:Framework45"
        }
        step([$class: 'MSTestPublisher', testResultsFile:"**/*.trx", failOnError: true, keepLongStdio: true])
    }
}

Unit and Acceptance Tests results

Unit and Acceptance Tests results

Stage Deploy to QA

Deploys package to QA IIS site, web.config is replaced by config file in Jenkins.

stage('Deploy to QA') {
  steps {
      bat "\"${MSDeploy}\" -source:package=\"%WORKSPACE%\\artifacts\\WebApp_${env.RELEASE_VERSION}.${env.BUILD_NUMBER}.zip\"  -verb:sync -dest:auto -allowUntrusted=true -setParam:name=\"IIS Web Application Name\",value=\"TestAppQA\""
      configFileProvider([configFile(fileId: 'web.QA.config', targetLocation: 'C:\\Jenkins_builds\\sites\\qa\\web.config')]) {}
  }
}

Stage Smoke Test QA

Smoke Test QA IIS site, using Powershell script.

stage('Smoke Test QA') {
  steps {
    smokeTest("http://localhost:8091/")
  }
}
...
void smokeTest(String url){
    def status = powershell (returnStatus: true, script: powershell ("""
		\$result = Invoke-WebRequest $url
		if (\$result.StatusCode -ne 200) {
			Write-Error \"Did not get 200 OK\"
			exit 1
		} else{
			Write-Host \"Successfully connect.\"
		}
    """)
    if (status != 0) {
       error "This pipeline stops here!"
    }
}

Stage Acceptance test

Runs acceptance tests using QA site.

stage('Acceptance test') {
    steps {
        dir('WebApplication.Tests.Acceptance\\bin\\Release')
        {
            bat "\"${VSTest}\" \"WebApplication.Tests.Acceptance.dll\" /Logger:trx;LogFileName=Results_${env.BUILD_NUMBER}.trx /Framework:Framework45"
        }
        step([$class: 'MSTestPublisher', testResultsFile:"**/*.trx", failOnError: true, keepLongStdio: true])
    }
}

Stage Deploy to Prod

This stage waits for input from user to deploy. Deploys package to Prod IIS site, web.config is replaced by config file in Jenkins.

stage('Deploy to Prod') {
  input {
    message 'Deploy to Prod?'
    ok 'Yes'
  }
  steps {
      bat "\"${MSDeploy}\" -source:package=\"%WORKSPACE%\\artifacts\\WebApp_${env.RELEASE_VERSION}.${env.BUILD_NUMBER}.zip\"  -verb:sync -dest:auto -allowUntrusted=true -setParam:name=\"IIS Web Application Name\",value=\"TestAppProd\""
      configFileProvider([configFile(fileId: 'web.Prod.config', targetLocation: 'C:\\Jenkins_builds\\sites\\prod\\web.config')]) {}
  }
} 

Input for Deploy to Prod stage

Stage Smoke Test Prod

Smoke Test Prod IIS site, using Powershell script.

stage('Smoke Test Prod') {
  steps {
    smokeTest("http://localhost:8092/")
  }
}

Post Section

Notification and archiving.

post { 
  failure { 
    slackSend (color: '#FF0000', message: "FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
    setBuildStatus("FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})", "FAILURE");
  }
  success{
    slackSend (color: '#00FF00', message: "SUCCESSFUL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
    setBuildStatus("SUCCESSFUL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})", "SUCCESS");
  }
  always {
    archiveArtifacts "artifacts\\WebApp_${env.RELEASE_VERSION}.${env.BUILD_NUMBER}.zip"
  }
}

Artifacts

Artifacts stored in Jenkins

Version

Github successful notification

Version

Slack notifications

Includes:

  • Jenkinsfile: for declarative pipeline on Jenkins, triggers from SCM on push to master branch, builds and deploys to local IIS Server.
  • web-deploy.ps1: powershell script that builds, deploys to file system and package web application.
  • web-publish.ps1: powershell script that builds, packages and deploys to IIS web application.
  • Docker/Dockerfile: Dockerfile for linux image with jenkins installed and plugins.
  • Docker/Dockerfile_Windows: Dockerfile for windows image(based on: https://blog.alexellis.io/continuous-integration-docker-windows-containers/)

Resources:

Pluralsight:

Using Declarative Jenkins Pipelines

Getting Started with Jenkins 2

Building a Modern CI/CD Pipeline with Jenkins

webapplication's People

Contributors

alanmacgowan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

webapplication's Issues

Implement Docker images w/Jenkins

-Linux container
-Windows container

.install default plugins
.create projects?
.windows: install tools (msbuild, msdeploy, nuget)

Implement Deployment Pipeline

-Stages: Commit - QA - Staging? - Prod

TODO:
-Paralell stages
-Secrets
-Set version number in environment
-input for Prod deploy
-move scripts to own files: powershell and groovy (shared libraries)
-Steps: code coverage, code metrics (sonarqube), smoke tests on deploy, performance tests
-Integrate with Issue Management

Server:
-Add nodes
-Get list of plugins installed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.