Skip to content

Commit 0b09f03

Browse files
committed
Merge remote-tracking branch 'origin/develop' into FEAT/open-id-connect-authentication
2 parents 0f588ba + 63d06da commit 0b09f03

File tree

189 files changed

+7722
-17786
lines changed

Some content is hidden

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

189 files changed

+7722
-17786
lines changed

.github/workflows/stale.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: 'Close stale issues and PRs'
2+
on:
3+
schedule:
4+
- cron: '30 1 * * *'
5+
workflow_dispatch:
6+
7+
jobs:
8+
stale:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/stale@v9
12+
with:
13+
stale-issue-label: 'stale'
14+
stale-pr-label: 'stale'
15+
stale-issue-message: 'Issue is now considered stale. If you want to keep it open, please comment :+1:'
16+
stale-pr-message: 'PR is now considered stale. If you want to keep it open, please comment :+1:'
17+
close-issue-message: 'Issue was closed due to inactivity.'
18+
close-pr-message: 'PR was closed due to inactivity.'
19+
days-before-stale: 182
20+
days-before-close: 365
21+
operations-per-run: 50

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@
33
._*
44
.vscode
55
certbot-help.txt
6+
test/node_modules
7+
*/node_modules
8+
docker/dev/dnsrouter-config.json.tmp
9+
docker/dev/resolv.conf

.version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.9.19
1+
2.11.3

Jenkinsfile

Lines changed: 112 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import groovy.transform.Field
2+
3+
@Field
4+
def shOutput = ""
5+
def buildxPushTags = ""
6+
17
pipeline {
28
agent {
39
label 'docker-multiarch'
@@ -8,14 +14,12 @@ pipeline {
814
ansiColor('xterm')
915
}
1016
environment {
11-
IMAGE = "nginx-proxy-manager"
17+
IMAGE = 'nginx-proxy-manager'
1218
BUILD_VERSION = getVersion()
13-
MAJOR_VERSION = "2"
14-
BRANCH_LOWER = "${BRANCH_NAME.toLowerCase().replaceAll('/', '-')}"
15-
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
16-
COMPOSE_FILE = 'docker/docker-compose.ci.yml'
19+
MAJOR_VERSION = '2'
20+
BRANCH_LOWER = "${BRANCH_NAME.toLowerCase().replaceAll('\\\\', '-').replaceAll('/', '-').replaceAll('\\.', '-')}"
21+
BUILDX_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
1722
COMPOSE_INTERACTIVE_NO_CLI = 1
18-
BUILDX_NAME = "${COMPOSE_PROJECT_NAME}"
1923
}
2024
stages {
2125
stage('Environment') {
@@ -26,7 +30,7 @@ pipeline {
2630
}
2731
steps {
2832
script {
29-
env.BUILDX_PUSH_TAGS = "-t docker.io/jc21/${IMAGE}:${BUILD_VERSION} -t docker.io/jc21/${IMAGE}:${MAJOR_VERSION} -t docker.io/jc21/${IMAGE}:latest"
33+
buildxPushTags = "-t docker.io/jc21/${IMAGE}:${BUILD_VERSION} -t docker.io/jc21/${IMAGE}:${MAJOR_VERSION} -t docker.io/jc21/${IMAGE}:latest"
3034
}
3135
}
3236
}
@@ -39,7 +43,7 @@ pipeline {
3943
steps {
4044
script {
4145
// Defaults to the Branch name, which is applies to all branches AND pr's
42-
env.BUILDX_PUSH_TAGS = "-t docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}"
46+
buildxPushTags = "-t docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}"
4347
}
4448
}
4549
}
@@ -54,106 +58,96 @@ pipeline {
5458
}
5559
}
5660
}
57-
stage('Frontend') {
58-
steps {
59-
sh './scripts/frontend-build'
60-
}
61-
}
62-
stage('Backend') {
63-
steps {
64-
echo 'Checking Syntax ...'
65-
sh 'docker pull nginxproxymanager/nginx-full:certbot-node'
66-
// See: https://github.com/yarnpkg/yarn/issues/3254
67-
sh '''docker run --rm \\
68-
-v "$(pwd)/backend:/app" \\
69-
-v "$(pwd)/global:/app/global" \\
70-
-w /app \\
71-
nginxproxymanager/nginx-full:certbot-node \\
72-
sh -c "yarn install && yarn eslint . && rm -rf node_modules"
73-
'''
74-
75-
echo 'Docker Build ...'
76-
sh '''docker build --pull --no-cache --squash --compress \\
77-
-t "${IMAGE}:ci-${BUILD_NUMBER}" \\
78-
-f docker/Dockerfile \\
79-
--build-arg TARGETPLATFORM=linux/amd64 \\
80-
--build-arg BUILDPLATFORM=linux/amd64 \\
81-
--build-arg BUILD_VERSION="${BUILD_VERSION}" \\
82-
--build-arg BUILD_COMMIT="${BUILD_COMMIT}" \\
83-
--build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \\
84-
.
85-
'''
61+
stage('Builds') {
62+
parallel {
63+
stage('Project') {
64+
steps {
65+
script {
66+
// Frontend and Backend
67+
def shStatusCode = sh(label: 'Checking and Building', returnStatus: true, script: '''
68+
set -e
69+
./scripts/ci/frontend-build > ${WORKSPACE}/tmp-sh-build 2>&1
70+
./scripts/ci/test-and-build > ${WORKSPACE}/tmp-sh-build 2>&1
71+
''')
72+
shOutput = readFile "${env.WORKSPACE}/tmp-sh-build"
73+
if (shStatusCode != 0) {
74+
error "${shOutput}"
75+
}
76+
}
77+
}
78+
post {
79+
always {
80+
sh 'rm -f ${WORKSPACE}/tmp-sh-build'
81+
}
82+
failure {
83+
npmGithubPrComment("CI Error:\n\n```\n${shOutput}\n```", true)
84+
}
85+
}
86+
}
87+
stage('Docs') {
88+
steps {
89+
dir(path: 'docs') {
90+
sh 'yarn install'
91+
sh 'yarn build'
92+
}
93+
}
94+
}
8695
}
8796
}
88-
stage('Integration Tests Sqlite') {
89-
steps {
90-
// Bring up a stack
91-
sh 'docker-compose up -d fullstack-sqlite'
92-
sh './scripts/wait-healthy $(docker-compose ps -q fullstack-sqlite) 120'
93-
94-
// Run tests
95-
sh 'rm -rf test/results'
96-
sh 'docker-compose up cypress-sqlite'
97-
// Get results
98-
sh 'docker cp -L "$(docker-compose ps -q cypress-sqlite):/test/results" test/'
97+
stage('Test Sqlite') {
98+
environment {
99+
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_sqlite"
100+
COMPOSE_FILE = 'docker/docker-compose.ci.yml:docker/docker-compose.ci.sqlite.yml'
99101
}
100-
post {
101-
always {
102-
// Dumps to analyze later
103-
sh 'mkdir -p debug'
104-
sh 'docker-compose logs fullstack-sqlite | gzip > debug/docker_fullstack_sqlite.log.gz'
105-
sh 'docker-compose logs db | gzip > debug/docker_db.log.gz'
106-
// Cypress videos and screenshot artifacts
107-
dir(path: 'test/results') {
108-
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
109-
}
110-
junit 'test/results/junit/*'
102+
when {
103+
not {
104+
equals expected: 'UNSTABLE', actual: currentBuild.result
111105
}
112106
}
113-
}
114-
stage('Integration Tests Mysql') {
115107
steps {
116-
// Bring up a stack
117-
sh 'docker-compose up -d fullstack-mysql'
118-
sh './scripts/wait-healthy $(docker-compose ps -q fullstack-mysql) 120'
119-
120-
// Run tests
121-
sh 'rm -rf test/results'
122-
sh 'docker-compose up cypress-mysql'
123-
// Get results
124-
sh 'docker cp -L "$(docker-compose ps -q cypress-mysql):/test/results" test/'
108+
sh 'rm -rf ./test/results/junit/*'
109+
sh './scripts/ci/fulltest-cypress'
125110
}
126111
post {
127112
always {
128113
// Dumps to analyze later
129-
sh 'mkdir -p debug'
130-
sh 'docker-compose logs fullstack-mysql | gzip > debug/docker_fullstack_mysql.log.gz'
131-
sh 'docker-compose logs db | gzip > debug/docker_db.log.gz'
132-
// Cypress videos and screenshot artifacts
133-
dir(path: 'test/results') {
134-
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
135-
}
114+
sh 'mkdir -p debug/sqlite'
115+
sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/sqlite/docker_fullstack.log 2>&1'
116+
sh 'docker logs $(docker-compose ps --all -q stepca) > debug/sqlite/docker_stepca.log 2>&1'
117+
sh 'docker logs $(docker-compose ps --all -q pdns) > debug/sqlite/docker_pdns.log 2>&1'
118+
sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/sqlite/docker_pdns-db.log 2>&1'
119+
sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/sqlite/docker_dnsrouter.log 2>&1'
136120
junit 'test/results/junit/*'
121+
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
137122
}
138123
}
139124
}
140-
stage('Docs') {
125+
stage('Test Mysql') {
126+
environment {
127+
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_mysql"
128+
COMPOSE_FILE = 'docker/docker-compose.ci.yml:docker/docker-compose.ci.mysql.yml'
129+
}
141130
when {
142131
not {
143132
equals expected: 'UNSTABLE', actual: currentBuild.result
144133
}
145134
}
146135
steps {
147-
dir(path: 'docs') {
148-
sh 'yarn install'
149-
sh 'yarn build'
150-
}
151-
152-
dir(path: 'docs/.vuepress/dist') {
153-
sh 'tar -czf ../../docs.tgz *'
136+
sh 'rm -rf ./test/results/junit/*'
137+
sh './scripts/ci/fulltest-cypress'
138+
}
139+
post {
140+
always {
141+
// Dumps to analyze later
142+
sh 'mkdir -p debug/mysql'
143+
sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/mysql/docker_fullstack.log 2>&1'
144+
sh 'docker logs $(docker-compose ps --all -q stepca) > debug/mysql/docker_stepca.log 2>&1'
145+
sh 'docker logs $(docker-compose ps --all -q pdns) > debug/mysql/docker_pdns.log 2>&1'
146+
sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/mysql/docker_pdns-db.log 2>&1'
147+
sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/mysql/docker_dnsrouter.log 2>&1'
148+
junit 'test/results/junit/*'
149+
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
154150
}
155-
156-
archiveArtifacts(artifacts: 'docs/docs.tgz', allowEmptyArchive: false)
157151
}
158152
}
159153
stage('MultiArch Build') {
@@ -164,78 +158,60 @@ pipeline {
164158
}
165159
steps {
166160
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
167-
// Docker Login
168-
sh "docker login -u '${duser}' -p '${dpass}'"
169-
// Buildx with push from cache
170-
sh "./scripts/buildx --push ${BUILDX_PUSH_TAGS}"
161+
sh 'docker login -u "${duser}" -p "${dpass}"'
162+
sh "./scripts/buildx --push ${buildxPushTags}"
171163
}
172164
}
173165
}
174-
stage('Docs Deploy') {
175-
when {
176-
allOf {
177-
branch 'master'
178-
not {
179-
equals expected: 'UNSTABLE', actual: currentBuild.result
166+
stage('Docs / Comment') {
167+
parallel {
168+
stage('Docs Job') {
169+
when {
170+
allOf {
171+
branch pattern: "^(develop|master)\$", comparator: "REGEXP"
172+
not {
173+
equals expected: 'UNSTABLE', actual: currentBuild.result
174+
}
175+
}
180176
}
181-
}
182-
}
183-
steps {
184-
withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'npm-s3-docs', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
185-
sh """docker run --rm \\
186-
--name \${COMPOSE_PROJECT_NAME}-docs-upload \\
187-
-e S3_BUCKET=jc21-npm-site \\
188-
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
189-
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
190-
-v \$(pwd):/app \\
191-
-w /app \\
192-
jc21/ci-tools \\
193-
scripts/docs-upload /app/docs/.vuepress/dist/
194-
"""
195-
196-
sh """docker run --rm \\
197-
--name \${COMPOSE_PROJECT_NAME}-docs-invalidate \\
198-
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
199-
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
200-
jc21/ci-tools \\
201-
aws cloudfront create-invalidation --distribution-id EN1G6DEWZUTDT --paths '/*'
202-
"""
203-
}
204-
}
205-
}
206-
stage('PR Comment') {
207-
when {
208-
allOf {
209-
changeRequest()
210-
not {
211-
equals expected: 'UNSTABLE', actual: currentBuild.result
177+
steps {
178+
build wait: false, job: 'nginx-proxy-manager-docs', parameters: [string(name: 'docs_branch', value: "$BRANCH_NAME")]
212179
}
213180
}
214-
}
215-
steps {
216-
script {
217-
def comment = pullRequest.comment("This is an automated message from CI:\n\nDocker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.")
181+
stage('PR Comment') {
182+
when {
183+
allOf {
184+
changeRequest()
185+
not {
186+
equals expected: 'UNSTABLE', actual: currentBuild.result
187+
}
188+
}
189+
}
190+
steps {
191+
script {
192+
npmGithubPrComment("Docker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.", true)
193+
}
194+
}
218195
}
219196
}
220197
}
221198
}
222199
post {
223200
always {
224-
sh 'docker-compose down --remove-orphans --volumes -t 30'
225201
sh 'echo Reverting ownership'
226-
sh 'docker run --rm -v $(pwd):/data jc21/ci-tools chown -R $(id -u):$(id -g) /data'
202+
sh 'docker run --rm -v "$(pwd):/data" jc21/ci-tools chown -R "$(id -u):$(id -g)" /data'
227203
}
228204
success {
229205
juxtapose event: 'success'
230206
sh 'figlet "SUCCESS"'
231207
}
232208
failure {
233-
archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true)
209+
archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
234210
juxtapose event: 'failure'
235211
sh 'figlet "FAILURE"'
236212
}
237213
unstable {
238-
archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true)
214+
archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
239215
juxtapose event: 'unstable'
240216
sh 'figlet "UNSTABLE"'
241217
}

0 commit comments

Comments
 (0)