Skip to content

Commit 3d15c7d

Browse files
authored
Merge pull request #145 from DontShaveTheYak/develop
Release v0.11.0
2 parents 1cd5cde + 5a0c6e3 commit 3d15c7d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1873
-74
lines changed

.devcontainer/Dockerfile

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
FROM jenkins/jenkins:latest-jdk11
2+
3+
# Install docker into the container
4+
USER root
5+
RUN apt-get update && \
6+
DEBIAN_FRONTEND=noninteractive apt-get install -y \
7+
wget \
8+
git \
9+
curl \
10+
python3 \
11+
python3-pip && \
12+
python3 -m pip install --upgrade pip && \
13+
rm -rf /var/lib/apt/lists/*
14+
15+
# Install and setup docker into the container
16+
RUN groupadd -g 118 docker && curl -fsSL https://get.docker.com -o get-docker.sh && \
17+
sh get-docker.sh && usermod -aG docker jenkins
18+
19+
USER jenkins
20+
21+
# Install pre-commit and dependencies
22+
COPY tests/requirements.txt /tmp
23+
RUN pip3 install --no-cache-dir -r /tmp/requirements.txt
24+
25+
## Plugins
26+
COPY --chown=jenkins:jenkins docker/*-plugins.txt /usr/share/jenkins/ref/
27+
RUN cat /usr/share/jenkins/ref/lib-plugins.txt >> /usr/share/jenkins/ref/runner-plugins.txt && \
28+
jenkins-plugin-cli -f /usr/share/jenkins/ref/runner-plugins.txt && \
29+
jenkins-plugin-cli --plugins job-dsl build-blocker-plugin
30+
31+
## Setup init scripts
32+
COPY --chown=jenkins:jenkins .devcontainer/*.groovy docker/init_scripts/src/main/groovy/* /usr/share/jenkins/ref/init.groovy.d/
33+
34+
ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false
35+
ENV JENKINS_SLAVE_AGENT_PORT=
36+
ENV JENKINS_OPTS="--httpPort=80"
37+
ENV PATH="/var/jenkins_home/.local/bin:$PATH"

.devcontainer/devcontainer.json

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
2+
// https://github.com/microsoft/vscode-dev-containers/tree/v0.191.1/containers/docker-existing-dockerfile
3+
{
4+
"name": "jenkins-std-lib",
5+
// Sets the run context to one level up instead of the .devcontainer folder.
6+
"context": "..",
7+
// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
8+
"dockerFile": "../.devcontainer/Dockerfile",
9+
// Set *default* container specific settings.json values on container create.
10+
"settings": {
11+
"editor.insertSpaces": true,
12+
"editor.tabSize": 4,
13+
"groovy.classpath": [
14+
"/var/jenkins_home/pipeline-library/build/dependencies"
15+
]
16+
},
17+
// Add the IDs of extensions you want installed when the container is created.
18+
"extensions": [
19+
"ms-azuretools.vscode-docker",
20+
"dontshavetheyak.jenkins-extension-pack",
21+
"eamodio.gitlens",
22+
"ms-python.python"
23+
],
24+
// By default vscode sets the entrypoint to infinite sleep loop
25+
"overrideCommand": false,
26+
// Put the workspace in the jenkins home directory so it can be installed into the jenkins as a shared library.
27+
"workspaceMount": "source=${localWorkspaceFolder},target=/var/jenkins_home/pipeline-library,type=bind,consistency=cached",
28+
"workspaceFolder": "/var/jenkins_home/pipeline-library",
29+
"containerEnv": {
30+
"DIND_WORKSPACE": "${localWorkspaceFolder}"
31+
},
32+
// Set the build args
33+
// "build": {
34+
// "args": {
35+
// "PRE_COMMIT_VERSION": "latest",
36+
// "TERRAFORM_VERSION": "latest",
37+
// "TERRAFORM_DOCS_VERSION": "latest",
38+
// "TERRASCAN_VERSION": "latest",
39+
// "TFLINT_VERSION": "latest",
40+
// "TFSEC_VERSION": "latest"
41+
// }
42+
// },
43+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
44+
// "forwardPorts": [8080, 50000],
45+
"appPort": [
46+
"5050:80"
47+
],
48+
// Uncomment the next line to run commands after the container is created - for example installing curl.
49+
"postStartCommand": "./gradlew downloadJars",
50+
// Uncomment when using a ptrace-based debugger like C++, Go, and Rust
51+
// "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
52+
// Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker.
53+
"mounts": [
54+
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
55+
],
56+
// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
57+
// "remoteUser": "vscode"
58+
}

.devcontainer/disable-security.groovy

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!groovy
2+
/* groovylint-disable NoDef, NoWildcardImports, UnnecessaryGetter, UnnecessarySetter, VariableTypeRequired */
3+
import jenkins.model.*
4+
import hudson.security.*
5+
import hudson.util.*
6+
import jenkins.install.*
7+
import javaposse.jobdsl.plugin.GlobalJobDslSecurityConfiguration
8+
import jenkins.model.GlobalConfiguration
9+
10+
// You should not actually do this on your real jenkins.
11+
println('==== Disable Jenkins Security')
12+
13+
println('== Disable JobDSL Security')
14+
GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration).useScriptSecurity = false
15+
GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration).save()
16+
17+
final Jenkins jenkins = Jenkins.getInstance()
18+
19+
println('== Disable Setup Wizard')
20+
jenkins.setInstallState(InstallState.INITIAL_SETUP_COMPLETED)
21+
22+
println('== Disable Authentication')
23+
def strategy = new AuthorizationStrategy.Unsecured()
24+
jenkins.setAuthorizationStrategy(strategy)
25+
26+
jenkins.save()
27+
println('== Disable Security complete')

.devcontainer/seed-job.groovy

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!groovy
2+
/* groovylint-disable GStringExpressionWithinString, JavaIoPackageAccess, NoDef, NoWildcardImports, UnnecessaryGetter, UnnecessaryObjectReferences, UnnecessarySetter, VariableTypeRequired */
3+
import hudson.model.FreeStyleProject
4+
import hudson.triggers.SCMTrigger
5+
import javaposse.jobdsl.plugin.*
6+
import jenkins.model.Jenkins
7+
import hudson.plugins.filesystem_scm.FSSCM
8+
9+
println('==== Creating seed job')
10+
final String jobName = 'seed-job'
11+
final File jobsDir = new File('/var/jenkins_home/pipeline-library/jobs')
12+
13+
final String dslScript = '''\
14+
import java.nio.file.Path
15+
import java.nio.file.Files
16+
import java.nio.file.Paths
17+
18+
19+
Files.walk(Paths.get('/var/jenkins_home/pipeline-library/jobs')).findAll { Path item ->
20+
item.toString().contains('.groovy')
21+
}.forEach { Path item ->
22+
final String fileName = item.getFileName()
23+
final String jobName = fileName.replace('_', '-').replace('.groovy', '')
24+
final File jenkinsFile = item.toFile()
25+
println("Creating job for ${fileName}")
26+
27+
pipelineJob(jobName) {
28+
29+
definition {
30+
cpsScm {
31+
32+
lightweight(true)
33+
34+
scm {
35+
filesystem {
36+
37+
// The file path for the source code.
38+
path(jenkinsFile.getParent())
39+
// If true, the system will delete all existing files/sub-folders in workspace before checking-out.
40+
clearWorkspace(false)
41+
// If true, the system will copy hidden files and folders as well.
42+
copyHidden(false)
43+
filterSettings {
44+
includeFilter(false)
45+
}
46+
47+
}
48+
}
49+
50+
scriptPath(fileName)
51+
52+
}
53+
}
54+
}
55+
}
56+
'''
57+
58+
final FSSCM fileScm = new FSSCM(jobsDir.getPath(), false, false, false, false, null)
59+
60+
final Jenkins jenkins = Jenkins.getInstance()
61+
62+
def existingJob = jenkins.items.find { def job ->
63+
job.name == jobName
64+
}
65+
66+
if (existingJob) {
67+
println('== Existing seed job found, exiting')
68+
return
69+
}
70+
71+
final SCMTrigger scmTrigger = new SCMTrigger('* * * * *')
72+
final ExecuteDslScripts dslBuilder = new ExecuteDslScripts()
73+
74+
// dslBuilder.setSandbox(true)
75+
dslBuilder.setScriptText(dslScript)
76+
dslBuilder.setUseScriptText(true)
77+
dslBuilder.setIgnoreExisting(false)
78+
dslBuilder.setIgnoreMissingFiles(false)
79+
dslBuilder.setFailOnMissingPlugin(true)
80+
dslBuilder.setRemovedJobAction(RemovedJobAction.DELETE)
81+
dslBuilder.setRemovedViewAction(RemovedViewAction.DELETE)
82+
dslBuilder.setLookupStrategy(LookupStrategy.JENKINS_ROOT)
83+
84+
dslProject = new FreeStyleProject(jenkins, jobName)
85+
dslProject.scm = fileScm
86+
87+
88+
dslProject.addTrigger(scmTrigger)
89+
dslProject.createTransientActions()
90+
dslProject.getPublishersList().add(dslBuilder)
91+
92+
println('== Adding Seed Job to Jenkins')
93+
jenkins.add(dslProject, jobName)
94+
95+
println('== Triggering Seed Job polling')
96+
scmTrigger.start(dslProject, true)
97+
98+
println('== Seed Job setup complete')

.groovylintrc.json

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
{
22
"extends": "recommended",
33
"rules": {
4+
"BlockEndsWithBlankLine": {
5+
"enabled": false
6+
},
47
"BlockStartsWithBlankLine": {
58
"enabled": false
69
},

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Changelog
22

3+
This has been deprecated until I can automate it, for now please see the GitHub [releases](https://github.com/DontShaveTheYak/jenkins-std-lib/releases).
4+
35
All notable changes to this project will be documented in this file.
46

57
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

CONTRIBUTING.md

+24-16
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,36 @@ In general, we follow the ["fork-and-pull" Git workflow](https://github.com/susa
3737
7. Open a PR in our repository so that we can efficiently review the changes.
3838

3939
### Code Style
40-
We are using GroovyLint to create a consistent experience when reading code. Besides GroovyLint we also ask that Class contructors only take a single argument and thats the workflow script. If you need additional aruguments for your class please use a property/field instead. We prefer this because when using our library to create jobs the user will almost never have autocompletion and groovy has poor support for keyword arguments.
41-
42-
Example:
43-
```groovy
44-
// Don't do this
45-
def myBook = new Book(this, 'A guide to Jenkins', 15)
46-
47-
// Do this
48-
def myBook = new Book(this)
49-
myBook.title = 'A guide to Jenkins'
50-
myBook.chapters = 15
51-
52-
// This might also be okay but usually only in methods
53-
def myBook = new Book(this, title: 'A guide to Jenkins', chapters: 15)
54-
```
40+
We are using GroovyLint to create a consistent experience when reading the source code. We do often ignore certain rules from GroovyLint like getter/setter rules so feel free to ignore a rule that you don't think applies.
5541

5642
### Setup
5743
The testing of this library is a little quirky. We currently test the library by creating Jenkins jobs in the [jobs](./jobs) folder. The format is `jobs/${packageName}/${className}_example.groovy` and this serves a basic example for users on how to use the class. You can also create unit tests using this format `jobs/${packageName}/tests/test_${className}.groovy`
5844

5945
We then use pytest to call a docker image that will run the jenkins job and return the output of the job. Pytest files use the following format `tests/test_${packageName}/test_${className}.py`
6046

61-
#### Development environment
47+
## Development environment
48+
49+
We highly recommend the development environment we have setup for [vscode](https://code.visualstudio.com/). This development environment contains all the tooling and dependencies you need to contribute to this project and will save you hours of time setting up these items manually.
50+
51+
### vscode
52+
53+
The requirements for using the vscode dev environment is to have the [remote-containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension installed.
54+
55+
When you first open this repository in vscode you will get a notification that this workspace contains a dev container. Click "**Reopen in Container**"
56+
57+
If you miss the notification you can manually open the workspace in a remote container by opening up the command palette `CTRL+SHIFT+P` and type `Open Workspace in Container`.
58+
59+
Note: The first time you open the workspace using the remote-container it will take 5-10mins to configure the development environment. The next time you use the remote-container it will open much faster.
60+
61+
Once opened in the dev container you can:
62+
* Run linting with `pre-commit run -a`
63+
* Open `http://localhost:5050` in your browser to access the Jenkins UI and run tests manually. When you click build on a job, it will automaticly use the latest job/library code.
64+
* Run all the tests in Jenkins UI automaticlly with `pytest -s`
65+
66+
### Manual
67+
68+
If you are not using docker or vscode you can setup a development environment using the following steps:
69+
6270
1. Have python (we use 3.9) installed and you should probably setup a venv. [Pyenv Guide](https://switowski.com/blog/pyenv)
6371
2. Install the python requirements.
6472
```

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ You can support my efforts in any of the following ways:
6464
* Star this repo! :star_struck:
6565
* Follow me on [Twitter](https://twitter.com/DontShaveTheYak).
6666
* Spread the word :grin:
67-
* Contribute to this repo! (Guide coming soon...ish)
67+
* Contribute to this repo using the [guide](./CONTRIBUTING.md)!
6868
* Sponsor me on [GitHub](https://github.com/sponsors/shadycuz) :heart_eyes:
6969
* Support me on [Patreon](https://www.patreon.com/DontShaveTheYak) :smiling_face_with_three_hearts:
7070
## License

build.gradle

+6-2
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,14 @@ repositories {
124124
}
125125
}
126126

127+
configurations {
128+
contrib.extendsFrom compileOnly
129+
}
130+
127131
dependencies {
128132
// Use the latest Groovy version for building this library
129133
compileOnly('org.codehaus.groovy:groovy-all:3.0.9')
130-
compileOnly('org.jenkins-ci.main:jenkins-core:2.313')
134+
compileOnly('org.jenkins-ci.main:jenkins-core:2.316')
131135
compileOnly('com.cloudbees:groovy-cps:1.32')
132136
}
133137

@@ -140,6 +144,6 @@ task downloadJars(type: Copy) {
140144

141145
into "${buildDir}/dependencies"
142146

143-
from configurations.compileOnly
147+
from configurations.contrib
144148

145149
}

docker/init_scripts/src/main/groovy/PipelineLibrary.groovy

+6-3
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,21 @@ final String repoBranch = 'master'
1313
final LibraryConfiguration lc
1414
final File file = new File('/var/jenkins_home/pipeline-library/src')
1515

16+
println('==== Setting up SharedLibray')
17+
1618
if (file.exists()) {
17-
println("===== Adding local ${libName}")
19+
println('== Adding local lib for development')
1820

1921
FSSCM scm = new FSSCM(file.getParent(), false, false, null)
2022

2123
lc = new LibraryConfiguration(libName, new SCMRetriever(scm))
2224

2325
} else {
24-
println("===== Adding remote ${libName}")
26+
println('== Adding remote lib for production use')
2527

2628
String repoURL = 'https://github.com/DontShaveTheYak/jenkins-std-lib'
2729

28-
println("===== Using the Pipeline library from ${repoURL}")
30+
println("== Using the Pipeline library from ${repoURL}")
2931

3032
GitSCMSource libSource = new GitSCMSource(libName, "${repoURL}.git", null, null, null, false)
3133

@@ -37,3 +39,4 @@ lc.with {
3739
defaultVersion = repoBranch
3840
}
3941
GlobalLibraries.get().libraries.add(lc)
42+
println('== SharedLibray setup complete')

docker/init_scripts/src/main/groovy/System.groovy

+9-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@ import jenkins.model.Jenkins
22
import jenkins.model.JenkinsLocationConfiguration
33
import hudson.tasks.Mailer
44

5-
println('== Configuring the system...')
5+
println('==== System Configuration')
66

77
// We do not wait for anything
88
Jenkins.instance.quietPeriod = 0
99

10-
JenkinsLocationConfiguration.get().adminAddress = 'admin@non.existent.email'
10+
// get Jenkins location configuration
11+
JenkinsLocationConfiguration config = JenkinsLocationConfiguration.get()
12+
13+
config.url = 'http://localhost:5050'
14+
config.adminAddress = 'admin@non.existent.email'
1115
Mailer.descriptor().defaultSuffix = '@non.existent.email'
16+
17+
config.save()
18+
println('== System Configuration complete')

docker/lib-plugins.txt

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
git:4.7.2
2-
sshd:3.0.3
1+
workflow-aggregator:2.6

docker/runner-plugins.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
configuration-as-code-groovy:1.1
22
filesystem_scm:2.1
33
jdk-tool:1.5
4+
git

0 commit comments

Comments
 (0)