Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set custom path for pipeline configuration file in the source code repository #252

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/concepts/pipeline-configuration/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ Pipeline Configurations can be stored in a couple different locations depending
| Job Type | Pipeline Configuration Location |
|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
| Pipeline Job | Either in the Jenkins UI or at the root of a remote source code repository as a file called `pipeline_config.groovy` |
| Multi-Branch Project | At the root of the repository in a file named `pipeline_config.groovy` in the branch job that was created as part of the Multi-Branch Project |
| Multi-Branch Project | At the root of the repository in a file named `pipeline_config.groovy` (or to any arbitrary path in the repository as configured by `configurationPath`) in the branch job that was created as part of the Multi-Branch Project |
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ If not, JTE will follow the flow described throughout the rest of this document.

### MultiBranch Project Pipeline Jobs

For MultiBranch Project Pipeline Jobs, if the source code repository has a `Jenkinsfile` at the root **and** `jte.allow_scm_jenkinsfile` is set to `True`, then the repository `Jenkinsfile` will be used as the Pipeline Template.
For MultiBranch Project Pipeline Jobs, if the source code repository has a `Jenkinsfile` at the root (or at any arbitrary path in the repository as configured by `scriptPath`) **and** `jte.allow_scm_jenkinsfile` is set to `True`, then the repository `Jenkinsfile` will be used as the Pipeline Template.

!!! important "Disabling Repository Jenkinsfiles"
It's important that when trying to enforce a certain set of Pipeline Templates are used that `jte.allow_scm_jenkinsfile` is set to `False`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import org.boozallen.plugins.jte.init.governance.config.ScmPipelineConfiguration
import org.boozallen.plugins.jte.init.governance.config.dsl.PipelineConfigurationDsl
import org.boozallen.plugins.jte.init.governance.config.dsl.PipelineConfigurationObject
import org.boozallen.plugins.jte.job.AdHocTemplateFlowDefinition
import org.boozallen.plugins.jte.job.MultibranchTemplateFlowDefinition
import org.boozallen.plugins.jte.util.FileSystemWrapper
import org.boozallen.plugins.jte.util.TemplateLogger
import org.jenkinsci.plugins.workflow.flow.FlowDefinition
Expand Down Expand Up @@ -74,7 +75,14 @@ class PipelineConfigurationAggregator {
} else {
// get job config if present
FileSystemWrapper fsw = FileSystemWrapper.createFromJob(flowOwner)
String repoConfigFile = fsw.getFileContents(ScmPipelineConfigurationProvider.CONFIG_FILE, "Template Configuration File", false)
// enable custom path to config file instead of default pipeline_config.groovy at root
String configurationPath
if (flowDefinition instanceof MultibranchTemplateFlowDefinition) {
configurationPath = flowDefinition.getConfigurationPath()
} else {
configurationPath = ScmPipelineConfigurationProvider.CONFIG_FILE
}
String repoConfigFile = fsw.getFileContents(configurationPath, "Template Configuration File", false)
if (repoConfigFile){
try{
jobConfig = new PipelineConfigurationDsl(flowOwner).parse(repoConfigFile)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package org.boozallen.plugins.jte.init
import org.boozallen.plugins.jte.init.governance.GovernanceTier
import org.boozallen.plugins.jte.init.governance.config.dsl.PipelineConfigurationObject
import org.boozallen.plugins.jte.job.AdHocTemplateFlowDefinition
import org.boozallen.plugins.jte.job.MultibranchTemplateFlowDefinition
import org.boozallen.plugins.jte.util.FileSystemWrapper
import org.boozallen.plugins.jte.util.TemplateLogger
import org.jenkinsci.plugins.workflow.flow.FlowDefinition
Expand Down Expand Up @@ -50,7 +51,14 @@ class PipelineTemplateResolver {
}
} else {
FileSystemWrapper fs = FileSystemWrapper.createFromJob(flowOwner)
String repoJenkinsfile = fs.getFileContents("Jenkinsfile", "Repository Jenkinsfile", false)
// enable custom path to template file instead of default Jenkinsfile at root
String templatePath
if (flowDefinition instanceof MultibranchTemplateFlowDefinition) {
templatePath = flowDefinition.getScriptPath()
} else {
templatePath = "Jenkinsfile"
}
String repoJenkinsfile = fs.getFileContents(templatePath, "Repository Jenkinsfile", false)
if (repoJenkinsfile){
if (jteBlockWrapper.allow_scm_jenkinsfile){
return repoJenkinsfile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,34 @@ import hudson.model.DescriptorVisibilityFilter
import org.jenkinsci.plugins.workflow.flow.FlowDefinitionDescriptor
import org.jenkinsci.plugins.workflow.job.WorkflowJob
import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject
import org.kohsuke.stapler.DataBoundSetter

/**
* Allows JTE to be used in a MultiBranch Pipeline
*/
class MultibranchTemplateFlowDefinition extends TemplateFlowDefinition {

String scriptPath
String configurationPath

@DataBoundSetter
void setScriptPath(String scriptPath){
this.scriptPath = scriptPath
}

String getScriptPath(){
return scriptPath
}

@DataBoundSetter
void setConfigurationPath(String configurationPath){
this.configurationPath = configurationPath
}

String getConfigurationPath(){
return configurationPath
}

@Extension
static class DescriptorImpl extends FlowDefinitionDescriptor {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import javax.annotation.Nonnull
*/
class TemplateBranchProjectFactory extends WorkflowBranchProjectFactory {

String configurationPath
Boolean filterBranches

// jenkins requires this be here
Expand All @@ -44,12 +45,24 @@ class TemplateBranchProjectFactory extends WorkflowBranchProjectFactory {
TemplateBranchProjectFactory(){}

Object readResolve() {
if (this.configurationPath == null) {
this.configurationPath = ScmPipelineConfigurationProvider.CONFIG_FILE
}
if (this.filterBranches == null) {
this.filterBranches = false
}
return this
}

@DataBoundSetter
void setConfigurationPath(String configurationPath){
this.configurationPath = configurationPath
}

String getConfigurationPath(){
return configurationPath
}

@DataBoundSetter
void setFilterBranches(Boolean filterBranches){
this.filterBranches = filterBranches
Expand All @@ -61,7 +74,10 @@ class TemplateBranchProjectFactory extends WorkflowBranchProjectFactory {

@Override
protected FlowDefinition createDefinition() {
return new MultibranchTemplateFlowDefinition()
MultibranchTemplateFlowDefinition definition = new MultibranchTemplateFlowDefinition()
definition.setScriptPath(this.scriptPath)
definition.setConfigurationPath(this.configurationPath)
return definition
}

@Override
Expand All @@ -75,20 +91,20 @@ class TemplateBranchProjectFactory extends WorkflowBranchProjectFactory {
}

// if user chose to filter branches, check for pipeline config file
SCMProbeStat stat = probe.stat(ScmPipelineConfigurationProvider.CONFIG_FILE)
SCMProbeStat stat = probe.stat(configurationPath)
switch (stat.getType()) {
case SCMFile.Type.NONEXISTENT:
if (stat.getAlternativePath() != null) {
listener.getLogger().format(" ‘%s’ not found (but found ‘%s’, search is case sensitive)%n", ScmPipelineConfigurationProvider.CONFIG_FILE, stat.getAlternativePath())
listener.getLogger().format(" ‘%s’ not found (but found ‘%s’, search is case sensitive)%n", configurationPath, stat.getAlternativePath())
} else {
listener.getLogger().format(" ‘%s’ not found%n", ScmPipelineConfigurationProvider.CONFIG_FILE)
listener.getLogger().format(" ‘%s’ not found%n", configurationPath)
}
return false
case SCMFile.Type.DIRECTORY:
listener.getLogger().format(" ‘%s’ found but is a directory not a file%n", ScmPipelineConfigurationProvider.CONFIG_FILE)
listener.getLogger().format(" ‘%s’ found but is a directory not a file%n", configurationPath)
return false
default:
listener.getLogger().format(" ‘%s’ found%n", ScmPipelineConfigurationProvider.CONFIG_FILE)
listener.getLogger().format(" ‘%s’ found%n", configurationPath)
return true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import jenkins.branch.OrganizationFolder
import jenkins.model.TransientActionFactory
import jenkins.scm.api.SCMSource
import jenkins.scm.api.SCMSourceCriteria
import org.boozallen.plugins.jte.init.governance.config.ScmPipelineConfigurationProvider
import org.jenkinsci.plugins.workflow.cps.Snippetizer
import org.jenkinsci.plugins.workflow.multibranch.AbstractWorkflowBranchProjectFactory
import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject
Expand All @@ -40,6 +41,8 @@ import org.kohsuke.stapler.DataBoundSetter
*/
class TemplateMultiBranchProjectFactory extends MultiBranchProjectFactory.BySCMSourceCriteria {

String scriptPath
String configurationPath
Boolean filterBranches

// jenkins requires this be here
Expand All @@ -48,12 +51,36 @@ class TemplateMultiBranchProjectFactory extends MultiBranchProjectFactory.BySCMS
TemplateMultiBranchProjectFactory(){}

Object readResolve() {
if (this.scriptPath == null) {
this.scriptPath = 'Jenkinsfile'
}
if (this.configurationPath == null) {
this.configurationPath = ScmPipelineConfigurationProvider.CONFIG_FILE
}
if (this.filterBranches == null) {
this.filterBranches = false
}
return this
}

@DataBoundSetter
void setScriptPath(String scriptPath){
this.scriptPath = scriptPath
}

String getScriptPath(){
return scriptPath
}

@DataBoundSetter
void setConfigurationPath(String configurationPath){
this.configurationPath = configurationPath
}

String getConfigurationPath(){
return configurationPath
}

@DataBoundSetter
void setFilterBranches(Boolean filterBranches){
this.filterBranches = filterBranches
Expand All @@ -72,6 +99,8 @@ class TemplateMultiBranchProjectFactory extends MultiBranchProjectFactory.BySCMS

private AbstractWorkflowBranchProjectFactory newProjectFactory() {
TemplateBranchProjectFactory factory = new TemplateBranchProjectFactory()
factory.setScriptPath(this.scriptPath)
factory.setConfigurationPath(this.configurationPath)
factory.setFilterBranches(this.filterBranches)
return factory
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler">
<f:entry title="Pipeline Template Path" field="scriptPath">
<f:textbox default="Jenkinsfile"/>
</f:entry>
<f:entry title="Pipeline Configuration Path" field="configurationPath">
<f:textbox default="pipeline_config.groovy"/>
</f:entry>
<f:entry title="${%Exclude branches without a pipeline configuration file}" field="filterBranches">
<f:checkbox default="false"/>
</f:entry>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p>
A Pipeline Configuration file that will be used when loading this Pipeline.
</p>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<div>
If checked, the Jenkins Templating Engine will exclude branches that do not have a Pipeline Configuration file (pipeline_config.groovy) at the root of the repository.

If unchecked, a pipeline will be created for all branches.
If checked, the Jenkins Templating Engine will exclude branches that do not have a Pipeline Configuration file
(pipeline_config.groovy) in the repository at the path specified by configurationPath.

If unchecked, a pipeline will be created for all branches.
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler">
<f:entry title="Pipeline Template Path" field="scriptPath">
<f:textbox default="Jenkinsfile"/>
</f:entry>
<f:entry title="Pipeline Configuration Path" field="configurationPath">
<f:textbox default="pipeline_config.groovy"/>
</f:entry>
<f:entry title="${%Exclude repository branches without a pipeline configuration file}" field="filterBranches">
<f:checkbox default="false"/>
</f:entry>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p>
A Pipeline Configuration file that will be used when loading this Pipeline.
</p>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<div>
If checked, the Jenkins Templating Engine will exclude branches that do not have a Pipeline Configuration file (pipeline_config.groovy) at the root of the repository.

If unchecked, a pipeline will be created for all branches.
If checked, the Jenkins Templating Engine will exclude branches that do not have a Pipeline Configuration file
(pipeline_config.groovy) in the repository at the path specified by configurationPath.

If unchecked, a pipeline will be created for all branches.
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p>
Relative location within the checkout of your Pipeline script.
</p>
Loading