192 lines
7.2 KiB
Groovy
192 lines
7.2 KiB
Groovy
branchName = 'main'
|
|
|
|
library identifier: "zorg-shared-lib@${branchName}",
|
|
retriever: modernSCM([
|
|
$class: 'GitSCMSource',
|
|
remote: "https://github.com/llvm/llvm-zorg.git"
|
|
])
|
|
|
|
pipeline {
|
|
options {
|
|
skipDefaultCheckout()
|
|
}
|
|
|
|
agent {
|
|
node {
|
|
label 'macos-trigger'
|
|
}
|
|
}
|
|
|
|
parameters {
|
|
string(name: 'GOOD_COMMIT', description: 'Known good commit SHA', defaultValue: '')
|
|
string(name: 'BAD_COMMIT', description: 'Known bad commit SHA', defaultValue: '')
|
|
choice(
|
|
name: 'TEST_JOB_NAME',
|
|
choices: [
|
|
'clang-stage1-RA',
|
|
'clang-stage1-RA-cmake-incremental',
|
|
'clang-stage1-RA-expensive',
|
|
'clang-stage1-RA-as',
|
|
'clang-san-iossim',
|
|
'clang-stage2-cmake-RgSan',
|
|
'clang-stage2-cmake-RgTSan',
|
|
'clang-stage2-Rthinlto',
|
|
],
|
|
description: 'Job to execute for testing each commit'
|
|
)
|
|
choice(
|
|
name: 'REPOSITORY',
|
|
choices: ['llvm-project'],
|
|
description: 'Repository to bisect'
|
|
)
|
|
booleanParam(name: 'RUN_TESTS', defaultValue: true, description: 'Run tests as part of bisection. Set to False if bisecting a build failure.')
|
|
string(name: 'SESSION_ID', description: 'Session ID to continue (optional)', defaultValue: '')
|
|
booleanParam(name: 'DRY_RUN', defaultValue: false, description: 'Dry run mode')
|
|
string(name: 'REQUESTOR', description: 'Email address of the requestor', defaultValue: '')
|
|
}
|
|
|
|
stages {
|
|
stage('Validate Parameters') {
|
|
steps {
|
|
script {
|
|
if (!params.GOOD_COMMIT || !params.BAD_COMMIT) {
|
|
error("Both GOOD_COMMIT and BAD_COMMIT parameters are required")
|
|
}
|
|
if (!params.TEST_JOB_NAME) {
|
|
error("TEST_JOB_NAME parameter is required")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Setup Repository') {
|
|
steps {
|
|
script {
|
|
echo "📁 Setting up repository: ${params.REPOSITORY}..."
|
|
|
|
dir(params.REPOSITORY) {
|
|
// Clone or checkout the repository
|
|
checkout([$class: 'GitSCM', branches: [
|
|
[name: params.GOOD_COMMIT]
|
|
], extensions: [
|
|
[$class: 'CloneOption',
|
|
timeout: 30]
|
|
], userRemoteConfigs: [
|
|
[url: 'https://github.com/llvm/llvm-project.git']
|
|
]])
|
|
|
|
// Verify commits exist
|
|
sh "git cat-file -e ${params.GOOD_COMMIT}"
|
|
sh "git cat-file -e ${params.BAD_COMMIT}"
|
|
|
|
echo "Repository setup complete"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Initialize Bisection') {
|
|
steps {
|
|
script {
|
|
bisectionManager.initializeBisection(
|
|
params.GOOD_COMMIT,
|
|
params.BAD_COMMIT,
|
|
params.TEST_JOB_NAME,
|
|
params.REPOSITORY,
|
|
params.SESSION_ID ?: null
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Execute Bisection') {
|
|
steps {
|
|
script {
|
|
def stepNumber = 1
|
|
def maxSteps = 50
|
|
|
|
while (stepNumber <= maxSteps) {
|
|
// Log step and get info
|
|
def stepInfo = bisectionManager.logStepStart(stepNumber, params.REPOSITORY)
|
|
|
|
if (stepInfo.type == 'complete') {
|
|
echo "Bisection complete! Failing commit: ${stepInfo.failing_commit}"
|
|
break
|
|
}
|
|
|
|
// Show restart instructions
|
|
bisectionManager.showRestartInstructions(stepNumber, params.TEST_JOB_NAME, params.REPOSITORY)
|
|
|
|
if (params.DRY_RUN) {
|
|
def simulatedResult = (stepNumber % 2 == 0) ? "SUCCESS" : "FAILURE"
|
|
echo "Simulated result: ${simulatedResult}"
|
|
bisectionManager.recordTestResult(stepInfo.commit, simulatedResult, params.REPOSITORY)
|
|
} else {
|
|
// Execute real job
|
|
def startTime = System.currentTimeMillis()
|
|
|
|
def jobResult = build(
|
|
job: "llvm.org/bisect/${params.TEST_JOB_NAME}",
|
|
parameters: [
|
|
string(name: 'GIT_SHA', value: stepInfo.commit),
|
|
string(name: 'BISECT_GOOD', value: stepInfo.bisection_range.current_good),
|
|
string(name: 'BISECT_BAD', value: stepInfo.bisection_range.current_bad),
|
|
booleanParam(name: 'IS_BISECT_JOB', value: true),
|
|
booleanParam(name: 'SKIP_TESTS', value: !params.RUN_TESTS),
|
|
booleanParam(name: 'SKIP_TRIGGER', value: true)
|
|
],
|
|
propagate: false,
|
|
wait: true
|
|
)
|
|
|
|
def duration = ((System.currentTimeMillis() - startTime) / 1000.0) as double
|
|
|
|
// Log the job execution
|
|
bisectionManager.logJobExecution(
|
|
params.TEST_JOB_NAME,
|
|
jobResult.result,
|
|
duration,
|
|
jobResult.absoluteUrl,
|
|
jobResult.number.toString(),
|
|
params.REPOSITORY
|
|
)
|
|
|
|
// Record the test result
|
|
bisectionManager.recordTestResult(stepInfo.commit, jobResult.result, params.REPOSITORY)
|
|
}
|
|
|
|
stepNumber++
|
|
sleep(2)
|
|
}
|
|
|
|
if (stepNumber > maxSteps) {
|
|
error("Bisection exceeded maximum steps")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Final Report') {
|
|
steps {
|
|
script {
|
|
bisectionManager.generateFinalReport(params.REPOSITORY)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
post {
|
|
always {
|
|
script {
|
|
bisectionManager.displaySummary(params.REPOSITORY)
|
|
archiveArtifacts artifacts: "bisection_state.json,bisection.log,restart_instructions.log,bisection_final_report.txt",
|
|
allowEmptyArchive: true
|
|
}
|
|
}
|
|
cleanup {
|
|
// Clean up but preserve artifacts
|
|
sh 'rm -f bisection_manager.py'
|
|
}
|
|
}
|
|
}
|