diff --git a/CHANGELOG.md b/CHANGELOG.md index 06a9ac5..309cc22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,27 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.3.3](https://github.com/stenic/jpipe/compare/v1.3.2...v1.3.3) (2023-03-24) + + +### Bug Fixes + +* github host-key entry https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/ ([b9a435b](https://github.com/stenic/jpipe/commit/b9a435bcdb4e42fe15f6d0f025e0b9bdf014536b)) + +## [1.3.2](https://github.com/stenic/jpipe/compare/v1.3.1...v1.3.2) (2023-03-24) + + +### Bug Fixes + +* Format and rebuild image ([068d8ab](https://github.com/stenic/jpipe/commit/068d8ab0b96172ad87a0c0ac781270a43ec21c03)) + +## [1.3.1](https://github.com/stenic/jpipe/compare/v1.3.0...v1.3.1) (2023-03-24) + + +### Bug Fixes + +* Format and rebuild image ([0bb9752](https://github.com/stenic/jpipe/commit/0bb9752a4ef14556b3fd87526ac7ffea702739ba)) + # [1.3.0](https://github.com/stenic/jpipe/compare/v1.2.2...v1.3.0) (2023-03-16) diff --git a/images/release/Dockerfile b/images/release/Dockerfile index bc06f08..80af598 100644 --- a/images/release/Dockerfile +++ b/images/release/Dockerfile @@ -15,8 +15,11 @@ RUN npm install -g \ WORKDIR /app RUN mkdir -p /home/node/.ssh/ \ - && ssh-keyscan -t rsa github.com >> /home/node/.ssh/known_hosts \ && ssh-keyscan -t rsa gitlab.com >> /home/node/.ssh/known_hosts \ - && ssh-keyscan -t rsa bitbucket.org >> /home/node/.ssh/known_hosts + && ssh-keyscan -t rsa bitbucket.org >> /home/node/.ssh/known_hosts \ + && ssh-keyscan -t rsa github.com >> /home/node/.ssh/known_hosts \ + && apk add --no-cache --virtual tooling jq curl \ + && curl -L https://api.github.com/meta | jq -r '.ssh_keys | .[]' | sed -e 's/^/github.com /' >> /home/node/.ssh/known_hosts \ + && apk del tooling ENTRYPOINT [""] diff --git a/resources/io/stenic/jpipe/release/release.config.js b/resources/io/stenic/jpipe/release/release.config.cjs similarity index 100% rename from resources/io/stenic/jpipe/release/release.config.js rename to resources/io/stenic/jpipe/release/release.config.cjs diff --git a/src/io/stenic/jpipe/plugin/CDInfraAsCodePlugin.groovy b/src/io/stenic/jpipe/plugin/CDInfraAsCodePlugin.groovy index 9641564..6303df1 100644 --- a/src/io/stenic/jpipe/plugin/CDInfraAsCodePlugin.groovy +++ b/src/io/stenic/jpipe/plugin/CDInfraAsCodePlugin.groovy @@ -5,26 +5,26 @@ import org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException class CDInfraAsCodePlugin extends Plugin { - private String yqDockerImage; - private String credentialId; - private String repository; - private String branch; - private String filePath; - private String yamlPath; - private String cdBranch; - private String gitUser; - private String gitEmail; + private String yqDockerImage + private String credentialId + private String repository + private String branch + private String filePath + private String yamlPath + private String cdBranch + private String gitUser + private String gitEmail CDInfraAsCodePlugin(Map opts = [:]) { - this.repository = opts.get('repository', ''); - this.credentialId = opts.get('credentialId', ''); - this.cdBranch = opts.get('cdBranch', 'main'); - this.branch = opts.get('branch', 'master'); - this.yamlPath = opts.get('yamlPath', '.image.tag'); - this.filePath = opts.get('filePath', 'values.yaml'); - this.gitUser = opts.get('gitUser', 'jpipe-ci'); - this.gitEmail = opts.get('gitEmail', 'jpipe@stenic.io'); - this.yqDockerImage = opts.get('dockerImage', 'mikefarah/yq:4'); + this.repository = opts.get('repository', '') + this.credentialId = opts.get('credentialId', '') + this.cdBranch = opts.get('cdBranch', 'main') + this.branch = opts.get('branch', 'master') + this.yamlPath = opts.get('yamlPath', '.image.tag') + this.filePath = opts.get('filePath', 'values.yaml') + this.gitUser = opts.get('gitUser', 'jpipe-ci') + this.gitEmail = opts.get('gitEmail', 'jpipe@stenic.io') + this.yqDockerImage = opts.get('dockerImage', 'mikefarah/yq:4') } public Map getSubscribedEvents() { @@ -36,25 +36,35 @@ class CDInfraAsCodePlugin extends Plugin { } public Boolean doYamlUpdate(Event event) { - if (this.cdBranch == "" || event.env.BRANCH_NAME != this.cdBranch) { - event.script.println("Skipping CDInfraAsCodePlugin") - return true; + if (this.cdBranch == '' || event.env.BRANCH_NAME != this.cdBranch) { + event.script.println('Skipping CDInfraAsCodePlugin') + return true } if (this.credentialId == '') { - this.credentialId = event.script.scm.getUserRemoteConfigs()[0].getCredentialsId(); + this.credentialId = event.script.scm.getUserRemoteConfigs()[0].getCredentialsId() } - event.script.dir( "${System.currentTimeMillis()}" ) { + if (this.hasPlugin('lockable-resources')) { + event.script.lock("infrarepo-${this.repository}") { + return this.doCommit(event) + } + } + + return this.doCommit(event) +} + + private Boolean doCommit(Event event) { + event.script.dir("${System.currentTimeMillis()}") { event.script.git( url: this.repository, branch: this.branch, credentialsId: this.credentialId, changelog: false - ); + ) event.script.docker.image(this.yqDockerImage).inside("--entrypoint=''") { - event.script.sh "yq eval --inplace '${this.yamlPath} = \"${event.version}\"' ${this.filePath}"; + event.script.sh "yq eval --inplace '${this.yamlPath} = \"${event.version}\"' ${this.filePath}" } event.script.sshagent(credentials: [this.credentialId]) { @@ -66,7 +76,14 @@ class CDInfraAsCodePlugin extends Plugin { event.script.sh "git push origin ${this.branch}" } } + } - return true + private Boolean hasPlugin(String pluginName) { + try { + return jenkins.model.Jenkins.instance.getPluginManager().getPlugin(pluginName) != null + } catch (RejectedAccessException e) { + return false + } } + } diff --git a/src/io/stenic/jpipe/plugin/ConventionalCommitPlugin.groovy b/src/io/stenic/jpipe/plugin/ConventionalCommitPlugin.groovy index 9eac3b4..ff3cba7 100644 --- a/src/io/stenic/jpipe/plugin/ConventionalCommitPlugin.groovy +++ b/src/io/stenic/jpipe/plugin/ConventionalCommitPlugin.groovy @@ -4,7 +4,7 @@ import io.stenic.jpipe.event.Event class ConventionalCommitPlugin extends Plugin { - protected String dockerImage = 'ghcr.io/stenic/jpipe-release:1.2' + protected String dockerImage = 'ghcr.io/stenic/jpipe-release:1.3' private Boolean useSemanticRelease = false private String releaseBranches @@ -81,7 +81,7 @@ class ConventionalCommitPlugin extends Plugin { private runRelease(script, cmdArgs) { Boolean configCreated = false - String configFile = 'release.config.js' + String configFile = 'release.config.cjs' if (!script.fileExists("./${configFile}")) { def releasercCfg = script.libraryResource "io/stenic/jpipe/release/${configFile}" script.writeFile file: configFile, text: releasercCfg diff --git a/src/io/stenic/jpipe/plugin/DockerPlugin.groovy b/src/io/stenic/jpipe/plugin/DockerPlugin.groovy index e3c217e..4c616ec 100644 --- a/src/io/stenic/jpipe/plugin/DockerPlugin.groovy +++ b/src/io/stenic/jpipe/plugin/DockerPlugin.groovy @@ -4,34 +4,34 @@ import io.stenic.jpipe.event.Event class DockerPlugin extends Plugin { - private String credentialId; - private String server; - private String repository; - private String buildArgs; - private String target; - private Boolean push; - private String filePath; - private String testScript; - private List extraTargets; - private List extraTags; - private Boolean useCache; - private Boolean doCleanup; - private String buildArgVersionKey; + private String credentialId + private String server + private String repository + private String buildArgs + private String target + private Boolean push + private String filePath + private String testScript + private List extraTargets + private List extraTags + private Boolean useCache + private Boolean doCleanup + private String buildArgVersionKey DockerPlugin(Map opts = [:]) { - this.repository = opts.get('repository', ''); - this.credentialId = opts.get('credentialId', ''); - this.server = opts.get('server', 'http://index.docker.io'); - this.buildArgs = opts.get('buildArgs', ''); - this.push = opts.get('push', this.credentialId != ''); - this.filePath = opts.get('filePath', '.'); - this.target = opts.get('target', ''); - this.extraTargets = opts.get('extraTargets', []); - this.extraTags = opts.get('extraTags', []); - this.testScript = opts.get('testScript', ''); - this.useCache = opts.get('useCache', true); - this.doCleanup = opts.get('doCleanup', false); - this.buildArgVersionKey = opts.get('buildArgVersionKey', 'VERSION'); + this.repository = opts.get('repository', '') + this.credentialId = opts.get('credentialId', '') + this.server = opts.get('server', 'http://index.docker.io') + this.buildArgs = opts.get('buildArgs', '') + this.push = opts.get('push', this.credentialId != '') + this.filePath = opts.get('filePath', '.') + this.target = opts.get('target', '') + this.extraTargets = opts.get('extraTargets', []) + this.extraTags = opts.get('extraTags', []) + this.testScript = opts.get('testScript', '') + this.useCache = opts.get('useCache', true) + this.doCleanup = opts.get('doCleanup', false) + this.buildArgVersionKey = opts.get('buildArgVersionKey', 'VERSION') } public Map getSubscribedEvents() { @@ -57,8 +57,8 @@ class DockerPlugin extends Plugin { this.extraTargets.each { target -> event.script.docker.image("${this.repository}:cache-${target}").pull() } - } catch(Exception e) {} - } + } catch (Exception e) { } + } def buildArgs = this.buildArgs if (this.target != '') { @@ -71,7 +71,7 @@ class DockerPlugin extends Plugin { event.script.sshagent(credentials: [event.script.scm.getUserRemoteConfigs()[0].getCredentialsId()]) { event.script.docker.build( "${this.repository}:${event.version}", - "${buildArgs} ${this.filePath}" + "${buildArgs} --build-arg ${this.buildArgVersionKey}=${event.version} ${this.filePath}" ) this.extraTags.each { tag -> event.script.sh "docker tag ${this.repository}:${event.version} ${this.repository}:${tag}" @@ -84,8 +84,8 @@ class DockerPlugin extends Plugin { } } } + } } - } public void doTest(Event event) { if (this.testScript != '') { @@ -108,11 +108,11 @@ class DockerPlugin extends Plugin { this.extraTargets.each { target -> event.script.docker.image("${this.repository}:${target}").push("cache-${target}") } - } catch(Exception e) {} + } catch (Exception e) { } + } } } } - } public void doDockerCleanup(Event event) { if (!this.doCleanup) { @@ -133,6 +133,7 @@ class DockerPlugin extends Plugin { } } event.script.sh 'docker rmi -f $(docker images -f "dangling=true" -q)' - } catch(Exception e) {} + } catch (Exception e) { } + } + } -} diff --git a/src/io/stenic/jpipe/plugin/EcrPlugin.groovy b/src/io/stenic/jpipe/plugin/EcrPlugin.groovy index d6a7274..a33a6d5 100644 --- a/src/io/stenic/jpipe/plugin/EcrPlugin.groovy +++ b/src/io/stenic/jpipe/plugin/EcrPlugin.groovy @@ -4,15 +4,15 @@ import io.stenic.jpipe.event.Event class EcrPlugin extends Plugin { - protected String dockerImage = 'amazon/aws-cli'; - private String credentialsId; - private String repository; - private String region; + protected String dockerImage = 'amazon/aws-cli' + private String credentialsId + private String repository + private String region EcrPlugin(Map opts = [:]) { - this.repository = opts.get('repository', ''); - this.credentialsId = opts.get('credentialsId', ''); - this.region = opts.get('region', ''); + this.repository = opts.get('repository', '') + this.credentialsId = opts.get('credentialsId', '') + this.region = opts.get('region', '') } public Map getSubscribedEvents() { @@ -41,4 +41,5 @@ class EcrPlugin extends Plugin { } } } + } diff --git a/src/io/stenic/jpipe/plugin/SecretFinderPlugin.groovy b/src/io/stenic/jpipe/plugin/SecretFinderPlugin.groovy index bdc2b97..d5e5ad6 100644 --- a/src/io/stenic/jpipe/plugin/SecretFinderPlugin.groovy +++ b/src/io/stenic/jpipe/plugin/SecretFinderPlugin.groovy @@ -5,7 +5,7 @@ import java.lang.Exception class SecretFinderPlugin extends Plugin { - public static final String TURTLEHOG = "TURTLEHOG"; + public static final String TRUFFELHOG = "TRUFFELHOG"; private Boolean allowFailure; private String trufflehogImage; @@ -14,7 +14,7 @@ class SecretFinderPlugin extends Plugin { SecretFinderPlugin(Map opts = [:]) { this.allowFailure = opts.get('allowFailure', false); this.trufflehogImage = opts.get('trufflehogImage', 'trufflesecurity/trufflehog:latest'); - this.scanners = opts.get('scanners', [this.TURTLEHOG]); + this.scanners = opts.get('scanners', [this.TRUFFELHOG]); } public Map getSubscribedEvents() { @@ -27,7 +27,7 @@ class SecretFinderPlugin extends Plugin { public void doScan(Event event) { try { - if (this.scanners.contains(this.TURTLEHOG)) { + if (this.scanners.contains(this.TRUFFELHOG)) { doTrufflehogScan(event) } } catch (Exception e) { diff --git a/src/io/stenic/jpipe/plugin/TrivyPlugin.groovy b/src/io/stenic/jpipe/plugin/TrivyPlugin.groovy index 70cc2a4..5121c94 100644 --- a/src/io/stenic/jpipe/plugin/TrivyPlugin.groovy +++ b/src/io/stenic/jpipe/plugin/TrivyPlugin.groovy @@ -12,7 +12,7 @@ class TrivyPlugin extends Plugin { private List severity; private String trivyVersion; private String report; - + TrivyPlugin(Map opts = [:]) { this.report = opts.get('report', 'table'); this.allowFailure = opts.get('allowFailure', false); @@ -45,6 +45,8 @@ class TrivyPlugin extends Plugin { ] if (this.report == 'html') { args.add('--format template --template "@contrib/html.tpl" -o /report/report.html') + } else if (this.report == 'json') { + args.add('--format json -o /report/report.json') } if (this.ignoreUnfixed == true) { args.add('--ignore-unfixed') @@ -80,6 +82,11 @@ class TrivyPlugin extends Plugin { reportFiles: 'report.html', reportName: "Trivy - ${imgName}", ]) + } else if (this.report == 'json') { + event.script.recordIssues tool: event.script.trivy( + pattern: ".trivy-report-${imgName}/report.json", + reportEncoding: 'UTF-8' + ) } } }