Clarify some details

This commit is contained in:
Benjamin Muschko
2019-11-18 17:11:32 -07:00
parent 248499c8f6
commit 57896f0303
17 changed files with 82 additions and 40 deletions

View File

@@ -1,12 +1,12 @@
# Exercise 1
In this exercise, you will practice installing and configuring Jenkins on your machine.
In this exercise, you will practice installing and configuring Jenkins on your machine. Feel free to experiment with a different Jenkins distribution than the proposed WAR file.
## Installing Jenkins
1. Download the [latest stable Jenkins WAR file](http://mirrors.jenkins.io/war-stable/latest/jenkins.war). To download from the command line, use `wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war`.
2. Open a terminal and navigate to the directory containing the WAR file.
3. Run the command `java -jar jenkins.war` to start Jenkins on port 8080. Provide the `--httpPort` option if you experience a port conflict e.g. `java -jar jenkins.war --httpPort=9999`. After a couple of seconds you should see the message "Jenkins is fully up and running" in the log output.
3. Run the command `java -jar jenkins.war` to start Jenkins on port 8080. Provide the `--httpPort` option if you experience a port conflict e.g. `java -jar jenkins.war --httpPort=9999`. For more information on starting and stopping Jenkins, see the [user guide](https://wiki.jenkins.io/display/JENKINS/Starting+and+Accessing+Jenkins). After a couple of seconds you should see the message "Jenkins is fully up and running" in the log output.
4. Open a browser of your choice and navigate to `localhost:<port>`. The default is `localhost:8080`.
5. In the screen named "Unlock Jenkins", enter the password from the console output. Press the "Continue" button.
6. In the screen named "Customize Jenkins", select the option "Install suggested plugins".

View File

@@ -5,10 +5,10 @@ In this exercise, you will create a new freestyle job and configure it to build
## Defining, Configuring and Organizing a Job
1. From the dashboard, click the "New Item" button.
2. Enter the item name "my-freestyle-job" and select "Freestyle project". Press the "OK" button.
2. Enter the item name `my-freestyle-job` and select "Freestyle project". Press the "OK" button.
3. In the job configuration, define the option to only keep the last 2 builds. Provide the description "A simple freestyle job". Upon building the project, a String parameter named `MESSAGE` should be provided. Press the "Save" button.
4. Trigger a new build by pressing the "Build with Parameters" button. Enter a value for the `MESSAGE` parameter. The build should finish successfully. Locate the provided parameter value in the build information.
5. Run the build two more times. What do you see?
6. Create a new view named "test". Add the job to the view.
7. Create a new folder named "freestyle" as part of the view. Move the job into the folder.
6. Create a new view named `test`. Add the job to the view.
7. Create a new folder named `freestyle` as part of the view. Move the job into the folder.
8. Locate the build information in `$JENKINS_HOME`. Inspect the directory structure.

View File

@@ -8,7 +8,7 @@ Configure the Git SCM and point the proper URL. The default is the `master` bran
![Git SCM](./images/git-scm.png)
Create the Gradle build step.
Create the Gradle build step. Ensure to select the "Use Gradle Wrapper" option.
![Git SCM](./images/gradle-build-step.png)
@@ -68,4 +68,4 @@ Build step 'Invoke Gradle script' changed build result to SUCCESS
Finished: SUCCESS
```
As a side note: The GitHub plugin is [currently broken](https://issues.jenkins-ci.org/browse/JENKINS-11337) if you wanted to build multiple branches with a single job. You will have to model it as a multi-branch pipeline job.
**As a side note:** The GitHub plugin is [currently broken](https://issues.jenkins-ci.org/browse/JENKINS-11337) if you wanted to build multiple branches with a single job. You will have to model it as a multi-branch pipeline job.

View File

@@ -8,7 +8,7 @@ In this exercise, you will configure the existing job to execute tests. Furtherm
2. Execute the build twice to generate a graph. Have a look at the executed tests in the test results.
3. Include all test results (unit and integration tests) in the reporting.
4. Have a look at how the test result trend changes.
5. Install the JaCoCo plugin.
5. Install the [JaCoCo plugin](https://plugins.jenkins.io/jacoco).
6. Reconfigure the Gradle build step to also generate JaCoCo reports: `clean build jacocoTestReport jacocoIntegrationTestReport`.
7. Add a post-build action for publish the JaCoCo reports. Use the following path to look for results: `build/jacoco/**.exec`.
8. Execute the build twice to generate a graph. Have a look at the code coverage results.

View File

@@ -16,7 +16,7 @@ The trend changes accordingly.
![Changed Test Result Trend](./images/all-test-result-trend.png)
Install the JaCoCo plugin.
Install the JaCoCo plugin from the Plugin Manager page.
![JaCoCo Plugin](./images/jacoco-plugin.png)

View File

@@ -8,7 +8,7 @@ You will enhance the existing job to generate a JAR file and store it on Jenkins
2. Execute the build. The build should list the artifact `gradle-initializr-1.0.0.jar`.
3. Have a look at the recorded fingerprints of this build.
4. Render the MD5 hash of the artifact and the usage of the artifact.
5. Install the Copy Artifacts plugin.
5. Install the [Copy Artifacts plugin](https://plugins.jenkins.io/copyartifact).
6. Create a downstream job named `consumer`.
7. Configure the downstream job to use the artifact produced by the upstream job.
8. Run the the build for the job `gradle-initializr`.

View File

@@ -12,7 +12,7 @@ Have a look at the details of the fingerprinting.
![Fingerprint Details](./images/fingerprint-details.png)
Install the Copy Artifacts plugin.
Install the Copy Artifacts plugin from the Plugin Manager page.
![Copy Artifacts Plugin](./images/copy-artifacts-plugin.png)

View File

@@ -2,16 +2,25 @@
You will start a VM using Vagrant as practice environment to set up a distributed build with 2 agents.
## Starting up the VMs
1. To start up the VMs, navigate to this directory. It should contain a `Vagrantfile`.
2. Run the command `vagrant up`. Bringing up the VMs might take some minutes. The two VMs will be available with the IP address `192.168.99.201` and `192.168.99.202`. The username/password credentials for those VMs are `jenkins:jenkins`.
## Configuring and Executing Jobs in a Distributed Build
1. Go to "Manage Jenkins" > "Manage Nodes". You should see a single `master` node.
2. Configure the `master` node by setting the # of executor value to 0. That will take care of never using the `master` for job workload.
3. Have other physical or virtual machines ready that can act as agent nodes. Log into the machine as `root` user and create a new user named `jenkins` with the commands `useradd -d /var/lib/jenkins jenkins` and `passwd jenkins`. From the `master` node, copy the contents of the `id_rsa.key` file to the clipboard. Paste the contents of the clipboard to the file `/var/lib/jenkins/.ssh/authorized_keys`.
4. Add new nodes by clicking "New Nodes". Enter an appropriate name and select the option "Permanent Agent". Use the remote directory `/home/jenkins/jenkins_slave` and set the # of executors to 2. Enter the host and provide credentials by selecting "SSH Username with private key". To keep things easy select "Non verifying Verification Strategy".
3. Add new nodes by clicking "New Nodes". Enter an appropriate name and select the option "Permanent Agent". Use the remote directory `/home/jenkins/jenkins_slave` and set the # of executors to 2. Enter the IP address `192.168.99.201` as host and provide credentials by selecting "Username with password". You will likely have to create a new credential. To keep things easy select "Non verifying Verification Strategy".
4. Trigger a build. You should see that the build is only executed on the agent and not the `master` node.
5. Add at least one more agent.
5. Add one more agent with the IP address `192.168.99.202`.
6. Trigger a build. You should see that the build can be executed on any of the agents.
7. Configure one of the agents to only build jobs with a specific label e.g. `java`. Change the "Usage" field to "Only build jobs with label expressions matching this node".
8. Configure the `gradle-initializr` job and assign the label `java`.
9. Trigger a build of the `gradle-initializr` job. It is only executed by the dedicated agent.
10. Trigger other jobs that do not have the label `java` assigned to them. They are waiting for an agent that can execute the build.
10. Trigger other jobs that do not have the label `java` assigned to them. They are waiting for an agent that can execute the build.
## Shutting down the VMs
1. After you are done with the exercise, navigate to the directory containing the `Vagrantfile`.
2. Tear down the VM by executing `vagrant destroy -f`.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 941 KiB

After

Width:  |  Height:  |  Size: 956 KiB

View File

@@ -1,14 +1,14 @@
# Exercise 11
In this exercise, you will set up a new multi-branch pipeline job and point it to an existing repository on GitHub. You will visualize the pipeline with the standard view and the Blue Ocean plugin.
In this exercise, you will set up a new multi-branch pipeline job and point it to an existing repository on GitHub. You will visualize the pipeline with the standard view and the Blue Ocean plugin. The job uses [SonarCloud](https://sonarcloud.io/) to capture static code analysis metrics and deploys the application to [Heroku](https://www.heroku.com/). You will need to create accounts for both services to follow along. Both services offer free tiers.
## Creating a Pipeline Job
1. Have a look at the [repository](https://github.com/bmuschko/todo-spring-boot) `bmuschko/todo-spring-boot` on GitHub. The repository already contains the build definition in the form of a `Jenkinsfile`. Identify each of the steps.
2. In Jenkins, set up the credentials `SONARCLOUD_TOKEN` and `HEROKU_API_KEY` if they don't exist yet.
1. Have a look at the [repository](https://github.com/bmuschko/todo-spring-boot) `bmuschko/todo-spring-boot` on GitHub. The repository already contains the build definition in the form of a `Jenkinsfile`. Identify each of the steps. Fork and clone the repository so you can later on create and push new branches.
2. In Jenkins, set up the credentials `SONARCLOUD_TOKEN` and `HEROKU_API_KEY` if they don't exist yet. The SonarCloud token can be retrieved under [My Account > Security](https://sonarcloud.io/account/security/). The Heroku API can be generated under [Account Settings > API Key](https://dashboard.heroku.com/account).
3. Create a new multi-branch pipeline job for the repository.
4. The initial build is triggered automatically. Have a look at the pipeline in the standard view and its console output.
5. Install the Blue Ocean plugin.
5. Install the [Blue Ocean plugin](https://plugins.jenkins.io/blueocean).
6. Open the Blue Ocean pipeline visualization for the job. Manually trigger the deployment step. Open a browser with the deployed application on Heroku.
7. Create a new branch named `bugfix` and push it to the remote repository. The code should be based off of `master`.
8. Select "Scan Multibranch Pipeline Now". The job should build the new branch.

View File

@@ -5,13 +5,13 @@ In this exercise, you'll create a declarative pipeline for a Go-based project. T
## Writing a Basic Jenkinsfile
1. Create a new GitHub repository named `go-on-jenkins`.
2. Create a new `Jenkinsfile` in the root directory of the repository as well as a simple `main.go` file. The main function just prints "Hello World!". Initialize the project via Go Modules.
2. Create a new `Jenkinsfile` in the root directory of the repository as well as a simple `main.go` file. The main function just prints "Hello World!". The repository https://github.com/bmuschko/go-helloworld-template shows an example.
3. Commit the files and push them to the remote repository.
4. Set up a new pipeline job for this repository in Jenkins.
5. Install the [Jenkins Go plugin](https://plugins.jenkins.io/golang).
6. Configure the latest Go runtime as global tool.
6. Configure the latest Go runtime as global tool. Use a name that reflects the Go version. Remember the name for the next step.
7. Enhance the `Jenkinsfile` based on the following requirements. The Jenkinsfile should use the declarative syntax.
* The job can run on all agents.
* The job sets the environment variable `GO111MODULES=on`.
* The job uses the Go runtime from the global tool definition.
* The job uses the Go runtime from the global tool definition (see previous step).
* The job specifies one build stage named "Build". The build stage executes the shell command `go build`.

View File

@@ -1,6 +1,6 @@
# Exercise 13
We'll want to enhance the pipeline by additional stages and implement a release workflow. The project is going to use an external tool called [GoReleaser](https://goreleaser.com/) to publish cross-compiled artifacts to [GitHub Releases](https://help.github.com/en/github/administering-a-repository/creating-releases). The binaries should only be released if the commit has been tagged.
We'll want to enhance the existing Go pipeline by additional stages and implement a release workflow. The project is going to use an external tool called [GoReleaser](https://goreleaser.com/) to publish cross-compiled artifacts to [GitHub Releases](https://help.github.com/en/github/administering-a-repository/creating-releases). The binaries should only be released if the commit has been tagged. You will need to create an account on [CodeCov](https://codecov.io/) and set up a [GitHub token](https://github.com/settings/tokens) to follow along.
## Enhancing a Pipeline With Advanced Features
@@ -8,13 +8,11 @@ We'll want to enhance the pipeline by additional stages and implement a release
* Add a build step that runs the shell command `go test ./...`.
* Generate code coverage metrics by adding the option `-coverprofile=coverage.txt` to the build step.
* Publish the code coverage metrics to CodeCov by sending a curl command `curl -s https://codecov.io/bash | bash -s -`.
* Log into [CodeCov](https://codecov.io/), determine the CodeCov token for the repository (aka Repository Upload Token) and set it up as credential in Jenkins.
* Retrieve the credential and set the value as environment variable named `CODECOV_TOKEN`.
2. Add a stage named `Code Analysis` that uses [golangci-lint](https://github.com/golangci/golangci-lint) to detect issues with the code.
* Add a build step for installing the `golangci-lint` with the shell command `curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.17.1`
* Add a build step for installing the `golangci-lint` with the shell command `curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.18.0`
* Add a build step that runs `golangci-lint` with the shell command `golangci-lint run`.
3. Add a stage named `Release` that uses [GoReleaser](https://github.com/goreleaser/goreleaser).
* Only build this step if the commit has been tagged.
* Set up a credential in Jenkins named `github_token` and set your GitHub token.
* Set up a credential in Jenkins named `github_token` and set your [GitHub token](https://github.com/settings/tokens). Create a new token if you didn't set up one yet.
* Retrieve the credential and set the value as environment variable named `GITHUB_TOKEN`.
* Add a build step that runs the shell command `curl -sL https://git.io/goreleaser | bash`.

View File

@@ -1,16 +1,9 @@
# Solution
Create the credentials for the CodeCov token.
![CodeCov Credentials](./images/codecov_token_credentials.png)
You can implement the "Test" stage as follows.
```groovy
stage('Test') {
environment {
CODECOV_TOKEN = credentials('CODECOV_TOKEN')
}
steps {
sh 'go test ./... -coverprofile=coverage.txt'
sh "curl -s https://codecov.io/bash | bash -s -"
@@ -23,7 +16,7 @@ You can implement the "Code Analysis" stage as follows.
```groovy
stage('Code Analysis') {
steps {
sh 'curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.17.1'
sh 'curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.18.0'
sh 'golangci-lint run'
}
}
@@ -47,4 +40,48 @@ stage('Release') {
sh 'curl -sL https://git.io/goreleaser | bash'
}
}
```
The final `Jenkinsfile` looks similar to the solution below.
```groovy
pipeline {
agent any
tools {
go 'go-1.12'
}
environment {
GO111MODULE = 'on'
}
stages {
stage('Build') {
steps {
sh 'go build'
}
}
stage('Test') {
steps {
sh 'go test ./... -coverprofile=coverage.txt'
sh "curl -s https://codecov.io/bash | bash -s -"
}
}
stage('Code Analysis') {
steps {
sh 'curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.18.0'
sh 'golangci-lint run'
}
}
stage('Release') {
when {
buildingTag()
}
environment {
GITHUB_TOKEN = credentials('GITHUB_TOKEN')
}
steps {
sh 'curl -sL https://git.io/goreleaser | bash'
}
}
}
}
```

View File

@@ -13,7 +13,7 @@ The directory structure of shared library repository should have the following s
Define the pipeline as global variable in the file `standard.groovy`.
```groovy
def call(String goToolName = 'go-1.12', String golangCiVersion = 'v1.12.5') {
def call(String goToolName = 'go-1.12', String golangCiVersion = 'v1.18.0') {
pipeline {
agent any
tools {
@@ -29,9 +29,6 @@ def call(String goToolName = 'go-1.12', String golangCiVersion = 'v1.12.5') {
}
}
stage('Test') {
environment {
CODECOV_TOKEN = credentials('CODECOV_TOKEN')
}
steps {
sh 'go test ./... -coverprofile=coverage.txt'
sh "curl -s https://codecov.io/bash | bash -s -"