├── .dockerignore
├── .github
├── dependabot.yml
├── release-drafter.yml
└── workflows
│ └── changelog.yml
├── .gitignore
├── Dockerfile
├── Jenkinsfile
├── LICENSE.md
├── Makefile
├── README.md
├── demo
├── locale-plugin
│ ├── .gitignore
│ └── repo
│ │ ├── Jenkinsfile
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── hudson
│ │ │ │ └── plugins
│ │ │ │ └── locale
│ │ │ │ ├── LocaleFilter.java
│ │ │ │ └── PluginImpl.java
│ │ ├── resources
│ │ │ ├── hudson
│ │ │ │ └── plugins
│ │ │ │ │ └── locale
│ │ │ │ │ └── PluginImpl
│ │ │ │ │ ├── config.jelly
│ │ │ │ │ ├── config.properties
│ │ │ │ │ └── config_zh_TW.properties
│ │ │ └── index.jelly
│ │ └── webapp
│ │ │ └── help
│ │ │ └── default-language.html
│ │ └── test
│ │ ├── java
│ │ └── hudson
│ │ │ └── plugins
│ │ │ └── locale
│ │ │ └── MigrationTest.java
│ │ └── resources
│ │ └── hudson
│ │ └── plugins
│ │ └── locale
│ │ └── MigrationTest
│ │ └── dataMigration_13
│ │ └── locale.xml
└── simple
│ └── Jenkinsfile
├── init_scripts
├── pom.xml
└── src
│ └── main
│ └── groovy
│ ├── PipelineLibrary.groovy
│ ├── System.groovy
│ └── Tools.groovy
├── jenkins-dev.yaml
├── jenkins.yaml
└── pom.xml
/.dockerignore:
--------------------------------------------------------------------------------
1 | # Repository
2 | .git
3 | .github
4 | .demo
5 | Makefile
6 | README.md
7 |
8 | # Custom WAR Packager
9 | .build
10 | tmp
11 |
12 | # Maven Packaging flow
13 | target
14 |
15 | # IDE
16 | .settings
17 | .idea
18 | .classpath
19 | .factoryclass
20 | .project
21 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "maven"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 | - package-ecosystem: "docker"
8 | directory: "/"
9 | schedule:
10 | interval: "weekly"
11 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | _extends: .github
2 | # We are using semver here
3 | version-template: $MAJOR.$MINOR.$PATCH
4 |
--------------------------------------------------------------------------------
/.github/workflows/changelog.yml:
--------------------------------------------------------------------------------
1 |
2 | # Automates creation of Release Drafts using Release Drafter
3 | # More Info: https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc
4 |
5 | on:
6 | push:
7 | branches:
8 | - master
9 |
10 | jobs:
11 | update_release_draft:
12 | runs-on: ubuntu-latest
13 | steps:
14 | # Drafts your next Release notes as Pull Requests are merged into "master"
15 | - uses: release-drafter/release-drafter@v5.11.0
16 | env:
17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Jenkins Config As Code Example.iml
2 | .build
3 | tmp/
4 | target
5 |
6 | # VS Code
7 | .factorypath
8 | .settings
9 | .project
10 | .classpath
11 |
12 | # IDEA
13 | .idea
14 | *.iml
15 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM jenkins/jenkinsfile-runner:build-mvncache as jfr-mvncache
2 |
3 | FROM jenkins/jenkinsfile-runner:1.0-beta-19 as jfr-base
4 |
5 | ###
6 | # Build stage
7 | ###
8 | FROM maven:3.5.4 as jfr-build
9 | ENV MAVEN_OPTS=-Dmaven.repo.local=/mavenrepo
10 | COPY --from=jfr-mvncache /mavenrepo /mavenrepo
11 | ADD pom.xml /jenkinsfile-runner/pom.xml
12 | RUN cd /jenkinsfile-runner && mvn clean package
13 | # TODO: Should be automated in Parent POM
14 | # Prepare the Jenkins core
15 | RUN mkdir /app && unzip /jenkinsfile-runner/target/war/jenkins.war -d /app/jenkins && \
16 | rm -rf /app/jenkins/scripts /app/jenkins/jsbundles /app/jenkins/css /app/jenkins/images /app/jenkins/help /app/jenkins/WEB-INF/detached-plugins /app/jenkins/winstone.jar /app/jenkins/WEB-INF/jenkins-cli.jar /app/jenkins/WEB-INF/lib/jna-4.5.2.jar
17 | # Delete HPI files and use the archive directories instead
18 | #RUN echo "Optimizing plugins..." && \
19 | # cd /jenkinsfile-runner/target/plugins && \
20 | # rm -rf *.hpi && \
21 | # for f in * ; do echo "Exploding $f..." && mv "$f" "$f.hpi" ; done;
22 |
23 | ####
24 | # Production image
25 | ####
26 | FROM adoptopenjdk:8u262-b10-jdk-hotspot
27 |
28 | LABEL Description="This is a base image for a single-shot ci.jenkins.io demo" Vendor="Oleg Nenashev" Version="0.3"
29 |
30 | # Packages
31 | RUN apt-get update && apt-get install -y wget git && rm -rf /var/lib/apt/lists/*
32 |
33 | # Maven
34 | ENV MAVEN_VERSION 3.6.3
35 | RUN curl -Lf https://downloads.apache.org/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz | tar -C /opt -xzv
36 | ENV M2_HOME /opt/apache-maven-$MAVEN_VERSION
37 | ENV maven.home $M2_HOME
38 | ENV M2 $M2_HOME/bin
39 | ENV PATH $M2:$PATH
40 |
41 | # JDK11
42 | RUN curl -L --show-error "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.8_10.tar.gz" --output adoptopenjdk.tar.gz && \
43 | echo "6e4cead158037cb7747ca47416474d4f408c9126be5b96f9befd532e0a762b47 adoptopenjdk.tar.gz" | sha256sum -c && \
44 | tar xvzf adoptopenjdk.tar.gz && \
45 | mkdir -p /usr/lib/jvm && \
46 | mv "jdk-11.0.8+10/" /usr/lib/jvm/jdk-11 && \
47 | rm adoptopenjdk.tar.gz
48 |
49 | COPY --from=jfr-build /jenkinsfile-runner/target/appassembler /app
50 | COPY --from=jfr-build /jenkinsfile-runner/target/plugins /usr/share/jenkins/ref/plugins
51 | COPY --from=jenkins/jenkinsfile-runner:1.0-beta-15 /app/bin/jenkinsfile-runner-launcher /app/bin/jenkinsfile-runner-launcher
52 | # /app/jenkins is a location of the WAR file. It can be empty in the current packaging
53 | RUN mkdir /app/jenkins
54 |
55 | VOLUME /usr/share/jenkins/ref/casc
56 |
57 | ENV JENKINS_HOME="/usr/share/jenkins/ref/"
58 | ENV JAVA_OPTS="-Djenkins.model.Jenkins.slaveAgentPort=50000 -Djenkins.model.Jenkins.slaveAgentPortEnforce=true -Dhudson.model.LoadStatistics.clock=1000"
59 | ENV CASC_JENKINS_CONFIG /usr/share/jenkins/ref/jenkins.yaml
60 | COPY jenkins.yaml /usr/share/jenkins/ref/jenkins.yaml
61 | COPY init_scripts/src/main/groovy/* /usr/share/jenkins/ref/init.groovy.d/
62 |
63 | ENTRYPOINT ["/app/bin/jenkinsfile-runner",\
64 | "-w", "/app/jenkins",\
65 | "-p", "/usr/share/jenkins/ref/plugins",\
66 | "-f", "/workspace/Jenkinsfile"]
67 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | properties([
2 | durabilityHint('PERFORMANCE_OPTIMIZED'),
3 | buildDiscarder(logRotator(numToKeepStr: '5')),
4 | ])
5 |
6 | timeout(time: 2, unit: 'HOURS') {
7 | node ("linux") {
8 | stage("Checkout") {
9 | checkout scm
10 | }
11 |
12 | stage ("Build") {
13 | def makeCommand = "make clean build"
14 | infra.runWithMaven(makeCommand)
15 | }
16 |
17 | stage("Run demo jobs") {
18 | stage("Smoke test") {
19 | sh "make run"
20 | }
21 | stage("Plugin build") {
22 | sh "make demo-plugin"
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Oleg Nenashev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Just a Makefile for manual testing
2 | .PHONY: all
3 |
4 | DOCKER_TAG=jenkins4eval/ci.jenkins.io-runner:local-test
5 | PIPELINE_LIBRARY_DIR=/Users/nenashev/Documents/jenkins/infra/pipeline-library/
6 | DOCKER_RUN_OPTS=-v maven-repo:/root/.m2
7 |
8 | all: clean build
9 |
10 | clean:
11 | rm -rf tmp
12 |
13 | .PHONY: docker
14 | docker:
15 | docker build -t $(DOCKER_TAG) .
16 |
17 | build: docker
18 |
19 | .PHONY: run
20 | run:
21 | docker run --rm ${DOCKER_RUN_OPTS} \
22 | -v $(CURDIR)/demo/simple/:/workspace/ \
23 | $(DOCKER_TAG)
24 |
25 | .PHONY: demo-plugin
26 | demo-plugin:
27 | docker run --rm ${DOCKER_RUN_OPTS} \
28 | -v $(CURDIR)/demo/locale-plugin/repo/:/workspace/ \
29 | $(DOCKER_TAG)
30 |
31 | .PHONY: demo-plugin-local-lib
32 | demo-plugin-local-lib:
33 | docker run --rm ${DOCKER_RUN_OPTS} \
34 | -v ${PIPELINE_LIBRARY_DIR}:/var/jenkins_home/pipeline-library \
35 | -v $(CURDIR)/demo/locale-plugin/repo:/workspace/ \
36 | $(DOCKER_TAG)
37 |
38 | .PHONY: jfr-profile
39 | jfr-profile:
40 | mkdir -p war-empty && \
41 | mkdir -p demo/locale-plugin/work && \
42 | cd demo/locale-plugin/work && \
43 | CASC_JENKINS_CONFIG=../../../jenkins-dev.yaml \
44 | JAVA_OPTS=-XX:StartFlightRecording=disk=true,dumponexit=true,filename=recording.jfr,maxsize=1024m,maxage=1d,settings=profile,path-to-gc-roots=true \
45 | ../../../target/appassembler/bin/jenkinsfile-runner \
46 | -p ../../../target/plugins/ -w war-empty -f ../repo/Jenkinsfile
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ci.jenkins.io-runner
2 | ===
3 |
4 | [](https://github.com/jenkinsci/ci.jenkins.io-runner/releases/latest)
5 | [](https://microbadger.com/images/onenashev/ci.jenkins.io-runner "Get your own image badge on microbadger.com")
6 | [](https://gitter.im/jenkinsci/jenkinsfile-runner)
7 |
8 | This project offers environment for running Jenkinsfile instances from ci.jenkins.io locally.
9 | It is powered by [Jenkinsfile Runner](https://github.com/jenkinsci/jenkinsfile-runner) and the experimental [JFR Maven packaging flow](https://github.com/jenkinsci/jenkinsfile-runner/tree/master/packaging-parent-pom) introduced in 1.0-beta-16.
10 | If you want a classic runtime Jenkins master with agents,
11 | checkout [my Jenkins Configuration-as-code demo](https://github.com/oleg-nenashev/demo-jenkins-config-as-code).
12 |
13 | The runner can execute `buildPlugin()` builds and some other commands from
14 | the [Jenkins Pipeline Library](https://github.com/jenkins-infra/pipeline-library).
15 | In particular, it is possible to run builds against multiple JDK and Jenkins core version combinations.
16 |
17 | See the _Limitations_ section below for some of known limitations.
18 |
19 | ### Quickstart
20 |
21 | 1. Checkout this repo
22 | 2. Run `make docker` to build the base image
23 | 3. Run `make run` to run a simple demo
24 | 4. Run `make demo-plugin` to run a demo of the plugin build
25 |
26 | ### Usage
27 |
28 | The runner can be invoked against a workspace which contains a `Jenkinsfile`
29 | and, if needed, the project's sourcecode.
30 |
31 | ```
32 | docker run --rm -v maven-repo:/root/.m2 \
33 | -v $(pwd)/demo/locale-plugin/:/workspace/ \
34 | onenashev/ci.jenkins.io-runner
35 | ```
36 |
37 | ### Developing Jenkins Pipeline Library
38 |
39 | Jenkins Pipeline library may be passed from a volume so that it is possible to test a local snapshot.
40 |
41 | ```
42 | docker run --rm -v maven-repo:/root/.m2 \
43 | -v ${MY_PIPELINE_LIBRARY_DIR}:/var/jenkins_home/pipeline-library \
44 | -v $(pwd)/demo/locale-plugin/:/workspace/ \
45 | onenashev/ci.jenkins.io-runner
46 | ```
47 |
48 | ### Developer notes
49 |
50 | #### Upgrade management
51 |
52 | This repository uses [Dependabot](https://dependabot.com/) to track dependencies and to propose updates.
53 | Many plugin and library dependencies actually come from Bills of Materials supplied by the JFR packaging parent POM:
54 | [Jenkins Core BOM](https://github.com/jenkinsci/jenkins/tree/master/bom) and
55 | [Jenkins Plugin BOM](https://github.com/jenkinsci/bom).
56 | It reduces the number of moving parts by consuming the cross-verified plugin versions.
57 |
58 | #### Debugging Jenkinsfile Runner
59 |
60 | To debug the execution, you can pass the `JFR_LOCAL_WORKSPACE=true` environment variable to the image.
61 | It will make the builder to execute Pipeline directly.
62 | It is also possible to debug Jenkinsfile Runner and Groovy init hooks by passing the remote debug options and exposing the debug port:
63 |
64 | ```
65 | docker run --rm -v maven-repo:/root/.m2 \
66 | -v $(pwd)/demo/locale-plugin/:/workspace/ \
67 | -p 5005:5005 -e JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=y" \
68 | onenashev/ci.jenkins.io-runner
69 | ```
70 |
71 | #### Profiling Jenkinsfile Runner
72 |
73 | This repository supports profiling of Jenkinsfile Runner with Java Flight Recorder.
74 | Due to performance reasons, profiling happens on a local machine instead of the Docker containers.
75 |
76 | To run profiling on a Unix machine:
77 |
78 | * Build ci.jenkins.io-runner locally via `mvn clean package`
79 | * Run `make jfr-profile` and wait till completion
80 | * Retrieve the `demo/locale-plugin/work/recording.jfr` file with Java Flight Recorder dump
81 | * Use performance analysis tools to analyze the Java Flight Recorder dump (e.g. IntelligIDEA, JDK Mission Control in AdoptOpenJDK).
82 | CPU and memory usage analysis can be done with the existing tools.
83 |
84 | ### Limitations
85 |
86 | This project has just started, so it has some downsides being compared
87 | to the runtime Pipeline Development instance [here](https://github.com/oleg-nenashev/demo-jenkins-config-as-code).
88 | All of the limitations below can be improved in the future.
89 |
90 | * A custom fork of Jenkins Pipeline Library is needed to run it
91 | * Follow https://github.com/jenkins-infra/pipeline-library/pull/78
92 | * `ci.jenkins.io-runner` is a single-container package with only 1 executor
93 | * Only JDK8 and JDK11 are provided in the image
94 | * Windows steps are not supported
95 | * Docker image is pretty big, because it bundles two versions of JDK
96 |
--------------------------------------------------------------------------------
/demo/locale-plugin/.gitignore:
--------------------------------------------------------------------------------
1 | # mvn
2 | /target/
3 |
4 | # jenkins
5 | work
6 |
7 | # idea
8 | .idea
9 | *.iml
10 |
11 | # vim
12 | .swp
13 |
--------------------------------------------------------------------------------
/demo/locale-plugin/repo/Jenkinsfile:
--------------------------------------------------------------------------------
1 | // Build the plugin using https://github.com/jenkins-infra/pipeline-library
2 | buildPlugin(jenkinsVersions: [null, '2.107.2'])
3 |
--------------------------------------------------------------------------------
/demo/locale-plugin/repo/README.md:
--------------------------------------------------------------------------------
1 | Locale Plugin for Jenkins
2 | =========================
3 |
4 | This plugin controls the language of Jenkins
5 |
6 | Normally, Jenkins honors the browser's language preference
7 | if a translation is available for the preferred language,
8 | and uses the system default locale for messages during a build.
9 |
10 | This plugin allows you to:
11 |
12 | * override the system default locale to the language of your choice
13 | * ignore browser's language preference completely
14 |
15 | This feature is sometimes convenient for multi-lingual environment.
16 |
17 | ### Usage
18 | Under _Manage Jenkins > Configure System_ there should be a "Locale" section.
19 |
20 | Here you can enter the _Default Language_: this should be a language code
21 | or locale code like "fr" (for French), or "de_AT" (German, in Austria).
22 |
23 | This value will be used by the system, for example, for messages that are printed
24 | to the log during a build (assuming that the Jenkins features and plugins that
25 | you're using have been translated into the specified language).
26 |
27 | To additionally force this language on all users, overriding their browser language,
28 | you can check the "Ignore browser preference and force this language to all users" option.
29 |
--------------------------------------------------------------------------------
/demo/locale-plugin/repo/pom.xml:
--------------------------------------------------------------------------------
1 |
7 | Internally, this uses Locale.setDefault(), so this affects 8 | all the other web applications that are running in the same container. 9 |