Select the correct set of instructions for your platform of choice:
There are two options for running Jenkins locally, you can either install Jenkins or run it through Docker. We would recommend running Jenkins through Docker and the instructions for that are here.
If you're on Windows make sure to run the commands in PowerShell rather than Git Bash to avoid issues with path expansion.
Once you've done the step above you should have Jenkins running on http://localhost:8080/. If you go to this url in a browser it should show you a setup page.
- Login with the password you got from the logs when starting Jenkins. Hint: You can run
docker logs your_container
to access a container's logs. Rundocker container ls
to view a list of running containers. - Now you have the option to select some initial plugins. Either select the suggested plugins or if you customise it, make sure you include the "Docker" plugin. We won't need any others right away, and you can add more later.
- Create an admin user.
- Use the default Jenkins URL (http://localhost:8080)
You should now see the Jenkins dashboard.
We now want to get Jenkins to build our app. To do this you need to create a job on Jenkins for our app and create a Jenkinsfile in your repository to define what the job should do.
From your Jenkins dashboard:
- Select New Item.
- Set it to a multibranch pipeline. This means the job will scan your repository for branches and run the job on any branch with a Jenkinsfile.
- Leave all the defaults other than setting the branch sources to GitHub. Leave the defaults for the branch source other than setting the repository url to your repository url. You may notice a warning about not using GitHub credentials at this point. This is fine, as we're just reading from a public repository we don't need credentials. If we were using a private repository or we were writing to the repository during the job, then we would need to set up credentials.
- Click Save to create the Jenkins job.
If the initial scan that it runs seems to be slow, see the hint below for how to adjust GitHub rate limiting.
See https://www.jenkins.io/doc/book/pipeline/jenkinsfile/ for details on how to create a Jenkinsfile. We want to add the same steps as for the GitHub Actions workflow so that it:
- Builds the C# code.
- Runs the C# tests.
- Builds the TypeScript code.
- Runs the linter on the TypeScript code.
- Runs the TypeScript tests.
You have 2 options for installing .NET Core & npm inside Jenkins:
- Make installation separate build stages
- This is not ideal as you will have to run the installation on each build
- Specify containers to run stages of the Jenkins pipeline with .NET Core and npm pre-installed
- The simplest approach is to have one stage for your
npm
commands and a second stage for yourdotnet
commands, because each stage can have its own agent. You will have to specifyagent none
at the top of the pipeline. - There are some pre-built images for npm (e.g.
node:17-bullseye
) - Similarly for .NET you can use Microsoft's image. You may need to set some environment variables in your Jenkinsfile for the dotnet CLI to work correctly:
DOTNET_CLI_HOME
(e.g. to"/tmp/dotnet_cli_home"
) andXDG_DATA_HOME
(e.g. to"/tmp"
).
- The simplest approach is to have one stage for your
Hints
- You'll need to use a
dir
block for some steps to run them inside theDotnetTemplate.Web
directory. - If Jenkins starts rate limiting your repository scanning you can go to "Manage Jenkins" -> "Configure System" and change "Github API usage rate limiting strategy" to "Throttle at/near rate limit". Adding credentials to your pipeline configuration will also increase the limit.
- Commit and push your new Jenkinsfile.
- From your Jenkins dashboard select the job you created.
- Click "Scan Repository Now" (exact wording may vary). This will scan the repository for branches and run the job on any branch with a Jenkinsfile.
- Select your branch, which should appear under "Branches" once the scan is done.
- You should see a stage view of the build, showing each stage in the Jenkinsfile. If the stage succeeded it will be green, if it failed it will be red.
- Select the most recent build from the build history on the left.
- Click "Console Output" to view the full logs from the build.
Once the repository scanning has picked up a branch you can build it again by clicking "Build Now" for that branch. You only need to scan the repository to check for new branches with Jenkinsfiles.
We want high test coverage, meaningfully testing as much of the functionality of the application as possible. Code coverage is a more naive metric - it simply checks which lines of code were executed during the test run. But higher code coverage is usually a good thing and it can still usefully flag which parts of the codebase are definitely untested. So let's include code coverage in our CI pipeline.
First check it works manually. From the DotnetTemplate.Web folder, run the command npm run test-with-coverage
. This runs the frontend tests and calculates code coverage at the same time.
It produces two reports: one in HTML form that you can open in your browser (DotnetTemplate.Web/coverage/index.html) and one in XML that we will get Jenkins to parse.
Try adding code coverage to Jenkins:
- Install the Code Coverage API plugin on Jenkins.
- Change your Jenkins pipeline to run the tests with code coverage.
- Add a step after running the tests to publish coverage. You can see a simple example of the command if you scroll down the Code Coverage API documentation, to the "pipeline example". You will want to use the "istanbulCoberturaAdapter", and the report to publish is "cobertura-coverage.xml" in the coverage folder.
- You should see a code coverage report appear on the build's page after it completes. Click through to see details.
Now let's enforce high code coverage:
- Configure it to fail the build for code coverage below 90%. You may find it easiest to use the Jenkins Snippet Generator.
- Push your change and watch the build go red!
- Edit the
DotnetTemplate.Web/Scripts/spec/exampleSpec.ts
file:
- Update the import statement:
import { functionOne, functionTwo } from '../home/example';
- Invoke functionTwo on a new line in the test
functionTwo();
- Push the change and observe the build go green again! You can also view the code coverage history.
Like for the GitHub Actions workflow, add slack notification to the Jenkins job. To make this work you will need to use the Slack app Jenkins CI, make sure this has been installed in the slack workspace you're using.
Note that their documentation may be slightly out of date and not quite match the page you see in Jenkins.
Can you create a single container that can be used as the sole build agent for the entire multistage Jenkins pipeline? You might need to do this to run end to end tests for example.