Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

wipe out workspace before deleting jobs #42

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
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
20 changes: 20 additions & 0 deletions Write-Feature-Properties.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<#
.SYNOPSIS
Retrieves the list of feature branches and writes them to a property file of the form
Features=feature_xxxx,feaure_yyyy,feature_zzzz

.EXAMPLE
Write-FeatureProperties -GitUrl https://user:[email protected]/revdotcom/revdotcom -OutFile branches.properties
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$True)] [string] $GitUrl,
[Parameter(Mandatory=$True)] [string] $OutFile
)

$branches = git ls-remote --heads $GitUrl
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$features = $branches | ? { $_ -match "\s+refs/heads/feature/(.*)$" } | % { $matches[1] }
$features = $features -Join ','
#use ASCII to avoid Out-File writing a Byte Order Mark
echo Features=$features | Out-File -Encoding ascii $OutFile
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ task syncWithRepo(dependsOn: 'classes', type: JavaExec) {
main = 'com.entagen.jenkins.Main'
classpath = sourceSets.main.runtimeClasspath
// pass through specified system properties to the call to main
['help', 'jenkinsUrl', 'jenkinsUser', 'jenkinsPassword', 'gitUrl', 'templateJobPrefix', 'templateBranchName', 'branchNameRegex', 'nestedView', 'printConfig', 'dryRun', 'startOnCreate', 'noViews', 'noDelete'].each {
['help', 'jenkinsUrl', 'jenkinsUser', 'jenkinsPassword', 'gitUrl', 'templateJobPrefix', 'templateBranchName',
'branchNameRegex', 'nestedView', 'printConfig', 'dryRun', 'startOnCreate', 'noViews', 'noDelete',
'cleanupJobName', 'deployJobBaseName', 'unitTestOnly'].each {
if (System.getProperty(it)) systemProperty it, System.getProperty(it)
}

Expand Down
29 changes: 23 additions & 6 deletions src/main/groovy/com/entagen/jenkins/JenkinsApi.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class JenkinsApi {
}

String getJobConfig(String jobName) {
// Please note that for this to work it requires that the authenticated user have ExtendedRead permission or it
// will return HTTP 403 (Forbidden). See `/role-strategy/manage-roles`.
def response = get(path: "job/${jobName}/config.xml", contentType: TEXT,
headers: [Accept: 'application/xml'])
response.data.text
Expand All @@ -62,9 +64,14 @@ class JenkinsApi {
}

void startJob(ConcreteJob job) {
println "Starting job ${job.jobName}."
println "Starting job ${job.jobName}"
post('job/' + job.jobName + '/build')
}

void startJobWithParameters(String jobName, postBody = [:]) {
println "Starting job ${jobName}"
post('job/' + jobName + '/build', postBody)
}

String configForMissingJob(ConcreteJob missingJob, List<TemplateJob> templateJobs) {
TemplateJob templateJob = missingJob.templateJob
Expand Down Expand Up @@ -96,6 +103,21 @@ class JenkinsApi {
post("job/${jobName}/doDelete")
}

void stopJob(String jobName) {
println "Stopping $jobName"
post("job/${jobName}/lastBuild/stop")
}

void wipeOutWorkspace(String jobName) {
println "wiping out workspace for job $jobName"
post("job/${jobName}/doWipeOutWorkspace")
}

void enableJob(String jobName) {
println "enable job $jobName"
post("job/${jobName}/enable")
}

void createViewForBranch(BranchView branchView, String nestedWithinView = null) {
String viewName = branchView.viewName
Map body = [name: viewName, mode: 'hudson.model.ListView', Submit: 'OK', json: '{"name": "' + viewName + '", "mode": "hudson.model.ListView"}']
Expand Down Expand Up @@ -191,11 +213,6 @@ class JenkinsApi {
params[crumbInfo.field] = crumbInfo.crumb
}






HTTPBuilder http = new HTTPBuilder(jenkinsServerUrl)

if (requestInterceptor) {
Expand Down
58 changes: 49 additions & 9 deletions src/main/groovy/com/entagen/jenkins/JenkinsJobManager.groovy
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.entagen.jenkins

import java.util.regex.Pattern
import groovy.json.JsonSlurper

class JenkinsJobManager {

String templateJobPrefix
String templateBranchName
String gitUrl
Expand All @@ -11,11 +13,12 @@ class JenkinsJobManager {
String branchNameRegex
String jenkinsUser
String jenkinsPassword

Boolean dryRun = false
Boolean noViews = false
Boolean noDelete = false
Boolean startOnCreate = false
Boolean failed = false

JenkinsApi jenkinsApi
GitApi gitApi
Expand All @@ -28,8 +31,10 @@ class JenkinsJobManager {
initGitApi()
}

void syncWithRepo() {
List<String> allBranchNames = gitApi.branchNames
Boolean syncWithRepo() {
this.failed = false

List<String> allBranchNames = gitApi.branchNames.unique{ it.toLowerCase() }
List<String> allJobNames = jenkinsApi.jobNames

// ensure that there is at least one job matching the template pattern, collect the set of template jobs
Expand All @@ -42,6 +47,8 @@ class JenkinsJobManager {
if (!noViews) {
syncViews(allBranchNames)
}

return this.failed
}

public void syncJobs(List<String> allBranchNames, List<String> allJobNames, List<TemplateJob> templateJobs) {
Expand All @@ -56,24 +63,57 @@ class JenkinsJobManager {
}

public void createMissingJobs(List<ConcreteJob> expectedJobs, List<String> currentJobs, List<TemplateJob> templateJobs) {
List<ConcreteJob> missingJobs = expectedJobs.findAll { !currentJobs.contains(it.jobName) }
List<String> lowercaseCurrentJobs = currentJobs.collect()*.toLowerCase()
List<ConcreteJob> missingJobs = expectedJobs.findAll { !lowercaseCurrentJobs.contains(it.jobName.toLowerCase()) }
if (!missingJobs) return

for(ConcreteJob missingJob in missingJobs) {
println "Creating missing job: ${missingJob.jobName} from ${missingJob.templateJob.jobName}"
jenkinsApi.cloneJobForBranch(missingJob, templateJobs)
if (startOnCreate) {
jenkinsApi.startJob(missingJob)
try {
// This creates missing jobs using the missingJob name. Note that templateJobs is a List.
jenkinsApi.cloneJobForBranch(missingJob, templateJobs)

// Rev.com-branch is -DtemplateJobPrefix
// Rev.com-branch-deploy- is the Jenkins job template
// Rev.com-branch-build- is the Jenkins job template

if (missingJob.jobName.contains("Rev.com-build-unittest")) {
// If the job contains unittest enable it. Jobs start out disabled so -deploy- will remain disabled.
jenkinsApi.enableJob(missingJob.jobName)
}
if (!missingJob.jobName.contains("Rev.com-deploy-unittest")) {
// Prevent double enabling of unittest jobs.
if (!missingJob.jobName.contains("Rev.com-build-unittest")) {
// If the job doesn't contain unittest enable it. Jobs start out disabled.
jenkinsApi.enableJob(missingJob.jobName)
}
}
if (startOnCreate && missingJob.jobName.contains("Rev.com-build-")) {
// Starting -build- has the downstream job of -deploy- when successful.
jenkinsApi.startJob(missingJob)
}
}
catch(Exception ex) {
println(ex.getMessage());
println(ex.getStackTrace());
this.failed = true
}
}

}

public void deleteDeprecatedJobs(List<String> deprecatedJobNames) {
if (!deprecatedJobNames) return
println "Deleting deprecated jobs:\n\t${deprecatedJobNames.join('\n\t')}"
deprecatedJobNames.each { String jobName ->
jenkinsApi.deleteJob(jobName)
try {
jenkinsApi.wipeOutWorkspace(jobName)
jenkinsApi.deleteJob(jobName)
}
catch(Exception ex) {
println(ex.getMessage());
println(ex.getStackTrace());
this.failed = true
}
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/main/groovy/com/entagen/jenkins/Main.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@ class Main {
k: [longOpt: 'no-delete', required: false, args: 0, argName: 'noDelete', description: "Do not delete (keep) branches and views - gradle flag -DnoDelete=true"],
f: [longOpt: 'filter-branch-names', required: false, args: 1, argName: 'branchNameRegex', description: "Only branches matching the regex will be accepted - gradle flag: -DbranchNameRegex=<regex>"],
usr: [longOpt: 'jenkins-user', required: false, args: 1, argName: 'jenkinsUser', description: "Jenkins username - gradle flag -DjenkinsUser=<jenkinsUser>"],
pwd: [longOpt: 'jenkins-password', required: false, args: 1, argName: 'jenkinsPassword', description: "Jenkins password - gradle flag -DjenkinsPassword=<jenkinsPassword>"]
pwd: [longOpt: 'jenkins-password', required: false, args: 1, argName: 'jenkinsPassword', description: "Jenkins password - gradle flag -DjenkinsPassword=<jenkinsPassword>"],
cu: [longOpt: 'cleanup-job-name', required: false, args: 1, argName: 'cleanupJobName', description: "Deploy Cleanup Job Name - gradle flag -DcleanupJobName=<cleanupJobName>"],
jd: [longOpt: 'deploy-base-job-name', required: false, args: 1, argName: 'deployJobBaseName', description: "Deploy base Job Name - gradle flag -DdeployJobBaseName=<deployJobBaseName>"],
]

public static void main(String[] args) {
Map<String, String> argsMap = parseArgs(args)
showConfiguration(argsMap)
JenkinsJobManager manager = new JenkinsJobManager(argsMap)
manager.syncWithRepo()

Boolean failure = manager.syncWithRepo()

if (failure) {
System.exit(1);
}
}

public static Map<String, String> parseArgs(String[] args) {
Expand Down