Skip to content

[GreenDragon] Duplicate and templatize clang-stage2-Rthinlto for bisection #533

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

Open
wants to merge 1 commit into
base: main
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
70 changes: 70 additions & 0 deletions zorg/jenkins/jobs/jobs/build-bisect
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env groovy
@Library('llvm-jenkins-lib') _

// Bisection orchestrator that manages the binary search process
// Uses build-bisect-run jobs to do the actual testing work
def bisectionUtils = evaluate readTrusted('zorg/jenkins/lib/utils/BisectionUtils.groovy')

pipeline {
options {
disableConcurrentBuilds()
}

parameters {
string(name: 'LABEL', defaultValue: params.LABEL ?: 'macos-x86_64', description: 'Node label to run on')
string(name: 'BISECT_GOOD', defaultValue: params.BISECT_GOOD ?: '', description: 'Known good commit')
string(name: 'BISECT_BAD', defaultValue: params.BISECT_BAD ?: '', description: 'Known bad commit')

// Job template configuration to pass through to build-bisect-run
string(name: 'JOB_TEMPLATE', defaultValue: params.JOB_TEMPLATE ?: 'clang-stage2-Rthinlto', description: 'Job template to bisect')
string(name: 'BUILD_CONFIG', defaultValue: params.BUILD_CONFIG ?: '{}', description: 'Build configuration JSON')
string(name: 'ARTIFACT', defaultValue: params.ARTIFACT ?: 'llvm.org/clang-stage1-RA/latest', description: 'Base artifact to use')
}

agent {
node {
label params.LABEL
}
}

stages {
stage('Setup') {
steps {
script {
if (!params.BISECT_GOOD || !params.BISECT_BAD || !params.JOB_TEMPLATE) {
error "BISECT_GOOD, BISECT_BAD, and JOB_TEMPLATE parameters are required"
}

echo "Starting bisection of ${params.JOB_TEMPLATE}: ${params.BISECT_GOOD}...${params.BISECT_BAD}"
echo "Build Config: ${params.BUILD_CONFIG}"

// Set build description
currentBuild.description = "🔍 BISECTING [${params.JOB_TEMPLATE}]: ${params.BISECT_GOOD.take(8)}..${params.BISECT_BAD.take(8)}"

// Clone the repository to get commit information
def clangBuilder = evaluate readTrusted('zorg/jenkins/lib/builders/ClangBuilder.groovy')
clangBuilder.checkoutStage()
}
}
}

stage('Perform Bisection') {
steps {
script {
def failingCommit = bisectionUtils.performBisectionWithRunner(
params.BISECT_GOOD,
params.BISECT_BAD,
params.JOB_TEMPLATE,
params.BUILD_CONFIG,
params.ARTIFACT
)

bisectionUtils.reportBisectionResult(failingCommit, params.JOB_TEMPLATE)

// Update build description with result
currentBuild.description = "✅ BISECTED [${params.JOB_TEMPLATE}]: failing commit ${failingCommit.take(8)}"
}
}
}
}
}
106 changes: 106 additions & 0 deletions zorg/jenkins/jobs/jobs/build-bisect-run
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#!/usr/bin/env groovy

// Generic build runner that can execute any job template configuration
// This job handles the actual building/testing work for bisection
def clangBuilder = evaluate readTrusted('zorg/jenkins/lib/builders/ClangBuilder.groovy')

pipeline {
options {
disableConcurrentBuilds()
}

parameters {
string(name: 'LABEL', defaultValue: params.LABEL ?: 'macos-x86_64', description: 'Node label to run on')
string(name: 'GIT_SHA', defaultValue: params.GIT_SHA ?: '*/main', description: 'Git commit to build.')
string(name: 'ARTIFACT', defaultValue: params.ARTIFACT ?: 'llvm.org/clang-stage1-RA/latest', description: 'Clang artifact to use')

// Job template configuration
string(name: 'JOB_TEMPLATE', defaultValue: params.JOB_TEMPLATE ?: 'clang-stage2-Rthinlto', description: 'Job template to use')
string(name: 'BUILD_CONFIG', defaultValue: params.BUILD_CONFIG ?: '{}', description: 'Build configuration JSON')

// Bisection context (for build description)
string(name: 'BISECT_GOOD', defaultValue: params.BISECT_GOOD ?: '', description: 'Good commit for bisection context')
string(name: 'BISECT_BAD', defaultValue: params.BISECT_BAD ?: '', description: 'Bad commit for bisection context')
}

agent {
node {
label params.LABEL
}
}

stages {
stage('Setup Build Description') {
steps {
script {
def commitInfo = params.GIT_SHA.take(8)
def template = params.JOB_TEMPLATE

if (params.BISECT_GOOD && params.BISECT_BAD) {
def goodShort = params.BISECT_GOOD.take(8)
def badShort = params.BISECT_BAD.take(8)
currentBuild.description = "🔍 BISECT RUN [${template}]: ${commitInfo} (${goodShort}..${badShort})"
} else {
currentBuild.description = "🔧 BUILD RUN [${template}]: ${commitInfo}"
}

echo "Job Template: ${template}"
echo "Testing commit: ${commitInfo}"
echo "Build Config: ${params.BUILD_CONFIG}"
}
}
}

stage('Checkout') {
steps {
script {
clangBuilder.checkoutStage()
}
}
}

stage('Setup Venv') {
steps {
script {
clangBuilder.setupVenvStage()
}
}
}

stage('Fetch Artifact') {
steps {
script {
clangBuilder.fetchArtifactStage()
}
}
}

stage('Build') {
steps {
script {
// Load the job template dynamically
def template = evaluate readTrusted("zorg/jenkins/lib/templates/${params.JOB_TEMPLATE}.groovy")

// Parse user build configuration
def userBuildConfig = [:]
if (params.BUILD_CONFIG && params.BUILD_CONFIG != '{}') {
userBuildConfig = readJSON text: params.BUILD_CONFIG
}

// Apply template defaults with user overrides
def buildConfig = template.getDefaultBuildConfig(userBuildConfig)

clangBuilder.buildStage(buildConfig)
}
}
}
}

post {
always {
script {
clangBuilder.cleanupStage()
}
}
}
}
1 change: 1 addition & 0 deletions zorg/jenkins/jobs/jobs/clang-stage2-Rthinlto-v2
49 changes: 49 additions & 0 deletions zorg/jenkins/jobs/jobs/templated-clang-job.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env groovy

/*
* GENERIC TEMPLATED CLANG JOB
*
* This is a generic job script that automatically configures itself based on the Jenkins job name.
* It works by using symlinks - each job is just a symlink to this file with the appropriate name.
*
* NAMING CONVENTION:
* - Job names follow the pattern: clang-stage[N]-[CONFIG]
* - Template name is derived by stripping any version suffix (e.g., -v2)
* - Each template defines its own bisection policy in getJobConfig()
*
* EXAMPLES:
* clang-stage2-Rthinlto-v2 → template: clang-stage2-Rthinlto, bisection: per template
* clang-stage1-RA → template: clang-stage1-RA, bisection: per template
* clang-stage2-cmake-RgSan → template: clang-stage2-cmake-RgSan, bisection: per template
*
* TEMPLATE RESOLUTION:
* - Templates are loaded from zorg/jenkins/lib/templates/[JOB_TEMPLATE].groovy
* - Template defines build configuration (stage, cmake_type, projects, etc.)
* - Template defines job configuration (bisection policy, etc.) via getJobConfig()
*
* TO ADD A NEW JOB:
* 1. Create the template file: zorg/jenkins/lib/templates/your-job-pattern.groovy
* 2. Create symlink: ln -s templated-clang-job.groovy your-job-name
* 3. Done! The job will automatically use the correct template and settings.
*
* BISECTION:
* - Each template decides its own bisection policy in getJobConfig()
* - ThinLTO jobs enable bisection (useful for performance regressions)
* - Stage1 jobs disable bisection (failures often environmental)
* - Future templates can define custom bisection logic
*/

def clangBuilder = evaluate readTrusted('zorg/jenkins/lib/builders/ClangBuilder.groovy')

// Auto-configure based on Jenkins job name
def jobName = env.JOB_NAME ?: 'unknown'

// Derive template name by stripping -v2 suffix if present
def templateName = jobName.replaceAll(/-v\d+$/, '')

// Load the template and get its job configuration
def template = evaluate readTrusted("zorg/jenkins/lib/templates/${templateName}.groovy")
def jobConfig = template.getJobConfig(jobName)

// Instantiate the templated pipeline
clangBuilder.createTemplatedPipeline(jobConfig).call()
Loading