diff --git a/Make.versions b/Make.versions index 8d01e37253..4fe5486634 100644 --- a/Make.versions +++ b/Make.versions @@ -64,7 +64,6 @@ MAC_PACKAGE_VERSION=8.13.0.$(MAC_COMMIT_DISTANCE) # numbers (major.minor) changes. # WARNING: Do **not** use versions higher than the available Xcode SDK or else we will have issues with mtouch (See https://github.com/xamarin/xamarin-macios/issues/7705) -# When bumping the major macOS version in MACOS_NUGET_VERSION also update the macOS version where we execute on bots in jenkins/Jenkinsfile (in the 'node' element) IOS_NUGET_OS_VERSION=15.4 TVOS_NUGET_OS_VERSION=15.4 diff --git a/jenkins/.gitignore b/jenkins/.gitignore deleted file mode 100644 index 8ba83de8c4..0000000000 --- a/jenkins/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -failure-stamp -pr-comments.md -build-failure.md -.tmp-labels* - diff --git a/jenkins/Jenkinsfile b/jenkins/Jenkinsfile deleted file mode 100644 index b6d388cd4a..0000000000 --- a/jenkins/Jenkinsfile +++ /dev/null @@ -1,1002 +0,0 @@ -#!/bin/groovy - -// global variables -repository = "xamarin/xamarin-macios" -commentFile = null -isPr = false -branchName = null -gitHash = null -packagePrefix = null -virtualPath = null -xiPackageUrl = null -xmPackageUrl = null -xiNotarizedPackageUrl = null -xmNotarizedPackageUrl = null -utils = null -errorMessage = null -currentStage = null -failedStages = [] -workspace = null -manualException = false - -xiPackageFilename = null -xmPackageFilename = null -xiNotarizedPkgFilename = null -xmNotarizedPkgFilename = null -msbuildZipFilename = null -bundleZipFilename = null -manifestFilename = null -artifactsFilename = null -reportPrefix = null -createFinalStatus = true -skipLocalTestRunReason = "" - -@NonCPS -def getRedirect () { - def connection = "${env.XAMARIN_BUILD_TASKS}".toURL().openConnection() - connection.instanceFollowRedirects = false - // should be in scope at the time of this call (called within a withCredentials block) - connection.setRequestProperty("Authorization", "token ${env.GITHUB_AUTH_TOKEN}") - def response = connection.responseCode - connection.disconnect() - if (response == 302) { - return connection.getHeaderField("Location") - } else { - throw new Exception("Failed to get redirect link for Xamarin.Build.Tasks: ${response}") - } -} - -github_pull_request_info = null -def githubGetPullRequestInfo () -{ - if (github_pull_request_info == null && isPr) { - withCredentials ([string (credentialsId: 'macios_github_comment_token', variable: 'GITHUB_PAT_TOKEN')]) { - def url = "https://api.github.com/repos/${repository}/pulls/${env.CHANGE_ID}" - def outputFile = ".github-pull-request-info.json" - try { - sh ("curl -vf -H 'Authorization: token ${GITHUB_PAT_TOKEN}' --output '${outputFile}' '${url}'") - github_pull_request_info = readJSON (file: outputFile) - echo ("Got pull request info: ${github_pull_request_info}") - } finally { - sh ("rm -f ${outputFile}") - } - } - - } - return github_pull_request_info -} - -github_pull_request_labels = null -def githubGetPullRequestLabels () -{ - if (github_pull_request_labels == null) { - github_pull_request_labels = [] - if (isPr) { - def pinfo = githubGetPullRequestInfo () - def labels = pinfo ["labels"] - if (labels != null) { - for (int i = 0; i < labels.size (); i++) { - def label = labels [i] - github_pull_request_labels.add (label ["name"]) - } - } - echo ("Found labels ${github_pull_request_labels} for the pull request.") - } - } - return github_pull_request_labels -} - -custom_labels = null -def getCustomLabels () -{ - if (custom_labels == null) { - custom_labels = [] - def custom_labels_file = "${workspace}/xamarin-macios/jenkins/custom-labels.txt" - if (fileExists (custom_labels_file)) { - def contents = sh (script: "grep -v '^[[:space:]]*#' ${custom_labels_file} | grep -v '^[[:space:]]*\$' | tr \$'\n' ' ' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*\$//'", returnStdout: true) - custom_labels += contents.tokenize (' ') - echo ("Found labels ${custom_labels} in ${custom_labels_file}") - } else { - echo ("The custom labels file ${custom_labels_file} does not exist") - } - } - return custom_labels -} - -labels = null -def getLabels () -{ - if (labels == null) { - labels = [] - labels += githubGetPullRequestLabels () - labels += getCustomLabels () - echo ("Found labels: ${labels}") - } - return labels -} - -def githubAddComment (url, markdown) -{ - if (markdown.length () > 32768) { - // GitHub only allows adding comments < 65536 characters log, so lets cap at half that, which should be more than enough to say that something went horribly wrong - markdown = markdown.substring (0, 32768) - } - - def json = groovy.json.JsonOutput.toJson ([body: markdown]) - def jsonFile = "${workspace}/xamarin-macios/jenkins/commit-comments.json" - try { - writeFile (file: "${jsonFile}", text: "${json}") - sh ("cat '${jsonFile}'") - withCredentials ([string (credentialsId: 'macios_github_comment_token', variable: 'GITHUB_COMMENT_TOKEN')]) { - sh ("curl -i -H 'Authorization: token ${GITHUB_COMMENT_TOKEN}' ${url} --data '@${jsonFile}'") - } - } finally { - sh ("rm -f ${jsonFile}") - } -} - -def commentOnCommit (commitHash, markdown) -{ - githubAddComment ("https://api.github.com/repos/${repository}/commits/${commitHash}/comments", markdown) -} - -def commentOnPullRequest (pullRequest, markdown) -{ - githubAddComment ("https://api.github.com/repos/${repository}/issues/${pullRequest}/comments", markdown) -} - -def addComment (markdown) -{ - if (isPr) { - commentOnPullRequest ("${env.CHANGE_ID}", markdown) - } else { - commentOnCommit ("${gitHash}", markdown) - } -} - -def appendFileComment (comment) -{ - if (fileExists (commentFile)) - comment = readFile (commentFile) + comment - - writeFile (file: commentFile, text: comment) -} - -def markdownToSlack (value) -{ - def tmpfile = "/tmp/slacker.md" - writeFile (file: tmpfile, text: value) - try { - // this monstruousity converts markdown's [text](url) to slack's - sh ("sed -i '' 's/[[]\\(.*\\)[]][\\(]\\(.*\\)[\\)]/<\\2|\\1>/' '${tmpfile}'") - value = readFile (tmpfile) - } finally { - sh ("rm -f '${tmpfile}'") - } - return value -} - -def reportFinalStatusToSlack (err, gitHash, currentStage, fileContents) -{ - def status = currentBuild.currentResult - if ("${status}" == "SUCCESS" && err == "") - return // not reporting success to slack - - try { - def authorName = null - def authorEmail = null - if (isPr) { - authorName = env.CHANGE_AUTHOR_DISPLAY_NAME - authorEmail = env.CHANGE_AUTHOR_EMAIL - slackMessage = "Pull Request #<${env.CHANGE_URL}|${env.CHANGE_ID}> failed to build." - } else { - authorName = sh (script: "cd ${workspace}/xamarin-macios && git log -1 --pretty=%an", returnStdout: true).trim () - authorEmail = sh (script: "cd ${workspace}/xamarin-macios && git log -1 --pretty=%ae", returnStdout: true).trim () - slackMessage = "Commit failed to build." - } - - def title = null - if (err != null) { - title = "Internal jenkins failed in stage '${currentStage}': ${err}" - } else { - title = "Internal jenkins failed in stage '${currentStage}'" - } - def text = "" - if (fileContents != null) - text = "\"text\": ${groovy.json.JsonOutput.toJson (markdownToSlack (fileContents))}," - // The attachments string must not start with a newline, it will produce a very helpful 'Invalid JSON String' exception with no additional info. - def attachments = """[ - { - \"author_name\": \"${authorName} (${authorEmail})\", - \"title\": \"${title}\", - \"title_link\": \"${env.RUN_DISPLAY_URL}\", - \"color\": \"danger\", - ${text} - \"fallback\": \"Build failed\" - } - ] - """ - echo (attachments) - slackSend (botUser: true, channel: "#ios-notifications", color: "danger", message: slackMessage, attachments: attachments) - } catch (e) { - echo ("Failed to report to Slack: ${e}") - } -} - -def reportFinalStatus (err, gitHash, currentStage) -{ - if (!createFinalStatus) - return - - def comment = "" - def status = currentBuild.currentResult - - if ("${status}" == "SUCCESS" && err == "" && failedStages.size () == 0) { - comment = "✅ [Jenkins job](${env.RUN_DISPLAY_URL}) (on internal Jenkins) succeeded" - } else { - // Aborted builds throw either a FlowInterruptedException or an AbortException (depending on what's executing), - // so treat either as an abortion (both can be thrown in other circumstances as well, so it's just a best guess). - if (err.contains ("FlowInterruptedException") || err.contains ("AbortException")) - comment += "❌ [Build was (probably) aborted](${env.RUN_DISPLAY_URL})\n\n" - comment += "đŸ”Ĩ [Jenkins job](${env.RUN_DISPLAY_URL}) (on internal Jenkins) failed" - if (currentStage != "" && !failedStages.contains (currentStage)) - failedStages.add (currentStage) - if (failedStages.size () > 0) { - // Somehow the same stage can end up in the list of failed stages multiple times. Avoid showing that to the user. - failedStages.unique () - comment += " in stage(s) '${failedStages.join (', ')}'" - } - comment += " đŸ”Ĩ" - if (!manualException && err != "") - comment += " : ${err}" - manager.addErrorBadge (comment) - manager.buildFailure () - } - - def fileContents = null - if (fileExists (commentFile)) { - fileContents = readFile ("${commentFile}") - comment += "\n\n" + fileContents - } - - addComment ("${comment}") - - reportFinalStatusToSlack (err, gitHash, currentStage, fileContents) -} - -def processAtMonkeyWrench (outputFile) -{ - def tmpfile = "atmonkeywrench.tmp" - try { - sh (script: "grep '^@MonkeyWrench: ...Summary: ' '${outputFile}' > ${tmpfile}", returnStatus: true /* don't throw exceptions if something goes wrong */) - def lines = readFile ("${tmpfile}").split ("\n") - for (int i = 0; i < lines.length; i++) { - def summary = lines [i].substring (27 /*"@MonkeyWrench: AddSummary: ".length*/).trim () - summary = summary.replace ("
", "") - summary = summary.replace ("") - if (href_end > 0) - summary = summary.substring (0, href_end) - echo (summary) - } - } finally { - sh ("rm -f '${tmpfile}'") - } -} - -def uploadFiles (glob, containerName, virtualPath) -{ - step ([ - $class: 'WAStoragePublisher', - allowAnonymousAccess: true, - cleanUpContainer: false, - cntPubAccess: true, - containerName: containerName, - doNotFailIfArchivingReturnsNothing: false, - doNotUploadIndividualFiles: false, - doNotWaitForPreviousBuild: true, - excludeFilesPath: '', - filesPath: glob, - storageAccName: 'bosstoragemirror', - storageCredentialId: 'bc6a99d18d7d9ca3f6bf6b19e364d564', - uploadArtifactsOnlyIfSuccessful: false, - uploadZips: false, - virtualPath: virtualPath, - storageType: 'blobstorage' - ]) -} - -@NonCPS -def getUpdateInfoAndVersion (file) -{ - def result = [:] - def match = file =~ /xamarin.(mac|ios)-(\d+(\.\d+)+).*.pkg$/ - if (match.matches()) { - result['platform'] = match[0][1] - result['version'] = match[0][2] - } - return result -} - -// There must be a better way than this hack to show a -// message in red in the Jenkins Blue Ocean UI... -def echoError (message) -{ - try { - error (message) - } catch (e) { - // Ignore - } -} - -def indexOfElement (list, element) -{ - for (def i = 0; i < list.size (); i++) { - if (list [i] == element) - return i - } - return -1 -} - -def runXamarinMacTests (url, macOS, maccore_hash, xamarin_macios_hash) -{ - def failed = false - def workspace = "${env.HOME}/jenkins/workspace/xamarin-macios" - def failedTests = [] - try { - echo ("Executing on ${env.NODE_NAME}") - echo ("URL: ${url}") - sh ("mkdir -p '${workspace}'") - dir ("${workspace}") { - // Download the script we need, and then execute it, so that we - // don't clone all of xamarin-macios to get a single file. - // Due to how github has implemented pull requests, this works - // even for pull requests from forks, since each commit in the pull request - // is also available from the main repository. - sh (""" - curl -fLO https://raw.githubusercontent.com/xamarin/xamarin-macios/${xamarin_macios_hash}/jenkins/prepare-packaged-macos-tests.sh - chmod +x prepare-packaged-macos-tests.sh - ./prepare-packaged-macos-tests.sh '${url}' '${maccore_hash}' - """) - def tests = [ "dontlink", "apitest", "introspection", "linksdk", "linkall", "xammac_tests" ]; - tests.each { test -> - def t = "${test}" - try { - timeout (time: 10, unit: 'MINUTES') { - sh ("make -C mac-test-package/tests exec-mac-${t} MONO_DEBUG=no-gdb-backtrace") - echo ("${t} succeeded") - } - } catch (error) { - echoError ("${t} failed with error: ${error}") - failed = true - failedTests.add (t) - } - } - // Run dontlink using the oldest system mono we support - def t = "dontlink (system)" - try { - // install oldest supported mono - sh ("./prepare-packaged-macos-tests.sh --install-old-mono") - // run dontlink tests using the system mono - sh ("make -C mac-test-package/tests exec-mac-system-dontlink") - } catch (error) { - echoError ("${t} failed with error: ${error}") - failed = true - failedTests.add (t) - } - } - } finally { - sh ("rm -rf ${workspace}/mac-test-package ${workspace}/*.zip ${workspace}/*.7z") - // Find and upload any crash reports - sh (script: """ - rm -Rf ${workspace}/crash-reports - mkdir ${workspace}/crash-reports - find ~/Library/Logs/DiagnosticReports/ -mtime -10m -exec cp {} ${workspace}/crash-reports \\; - ls -la ${workspace}/crash-reports - """, - returnStatus: true /* Don't fail if something goes wrong */) - try { - if (findFiles (glob: "crash-reports/*").length > 0) { - archiveArtifacts ("${workspace}/crash-reports/*") - } else { - echo ("No crash reports found") - } - } catch (e) { - // Ignore any archiving errors. - } - } - if (failed) { - def failureMessage = "Xamarin.Mac tests on ${macOS} failed (${failedTests.join (', ')})" - manager.addErrorBadge (failureMessage) - error (failureMessage) - } -} - -def abortExecutingBuilds () -{ - def job = Jenkins.instance.getItemByFullName (env.JOB_NAME) - for (build in job.builds) { - if (!build.isBuilding ()) - continue - echo ("Current build: ${currentBuild.number} Checking build: ${build.number}"); - if (build.number > currentBuild.number) { - error ("There is already a newer build in progress (#${build.number})") - } else if (build.number < currentBuild.number) { - def exec = build.getExecutor () - if (exec == null) { - echo ("No executor for build ${build.number}") - } else { - exec.interrupt (Result.ABORTED, new CauseOfInterruption.UserInterruption ("Aborted by build #${currentBuild.number}")) - echo ("Aborted previous build: #${build.number}") - } - } - } -} - -timestamps { - def mainMacOSVersion = "10.15" - node ("xamarin-macios && macos-${mainMacOSVersion}") { - try { - timeout (time: 15, unit: 'HOURS') { - // Hard-code a workspace, since branch-based and PR-based - // builds would otherwise use different workspaces, which - // wastes a lot of disk space. - workspace = "${env.HOME}/jenkins/workspace/xamarin-macios" - commentFile = "${workspace}/xamarin-macios/jenkins/pr-comments.md" - withEnv ([ - "BUILD_REVISION=jenkins", - "PATH=/Library/Frameworks/Mono.framework/Versions/Current/Commands:${env.PATH}", - "WORKSPACE=${workspace}" - ]) { - sh ("mkdir -p '${workspace}/xamarin-macios'") - dir ("${workspace}/xamarin-macios") { - stage ('Checkout') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - sh ("env | sort") // Print out environment for debug purposes - - branchName = env.BRANCH_NAME - echo ("Branch name: ${branchName}") - - scmVars = checkout scm - isPr = (env.CHANGE_ID && !env.CHANGE_ID.empty ? true : false) - if (isPr) { - gitHash = sh (script: "git log -1 --pretty=%H refs/remotes/origin/${env.BRANCH_NAME}", returnStdout: true).trim () - } else { - gitHash = scmVars.GIT_COMMIT - } - // Make sure we start from scratch - sh (script: 'make git-clean-all', returnStatus: true /* don't throw exceptions if something goes wrong */) - // Make really, really sure - sh ('git clean -xffd') - sh ('git submodule foreach --recursive git clean -xffd') - } - } - - if (isPr) { - def hasBuildPackage = getLabels ().contains ("build-package") - def hasRunInternalTests = getLabels ().contains ("run-internal-tests") - - if (!hasBuildPackage && !hasRunInternalTests) { - // don't add a comment to the pull request, since the public jenkins will also add comments, which ends up being too much. - createFinalStatus = false - echo ("Build skipped because the pull request doesn't have either of the labels 'build-package' or 'run-internal-tests'.") - return - } - - if (!hasRunInternalTests) - skipLocalTestRunReason = "Not running tests here because they're run on public Jenkins." - - // only aborting PR builds, since for normal branches we want to build as much as possible by default. - abortExecutingBuilds () - } - - dir ("${workspace}") { - stage ('Cleanup') { - currentStage = "${STAGE_NAME}" - echo ("Cleaning up on ${env.NODE_NAME}") - sh ("${workspace}/xamarin-macios/jenkins/clean-jenkins-bots.sh") - } - - stage ('Provisioning') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - sh ("cd ${workspace}/xamarin-macios && ./configure --enable-xamarin") - sh ("${workspace}/xamarin-macios/jenkins/provision-deps.sh") - } - - stage ('Build') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - timeout (time: 1, unit: 'HOURS') { - withEnv ([ - "CURRENT_BRANCH=${branchName}", - "PACKAGE_HEAD_BRANCH=${branchName}" - ]) { - sh ("${workspace}/xamarin-macios/jenkins/build.sh --configure-flags --enable-xamarin") - } - } - } - - // Delete any packages we might have - the package directory might have packages from previous builds. - sh (script: "rm -Rf ${workspace}/package", returnStatus: true /* don't throw exceptions if something goes wrong */) - - stage ('Packaging') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - def skipPackages = getLabels ().contains ("skip-packages") - if (!skipPackages) { - sh ("${workspace}/xamarin-macios/jenkins/build-package.sh") - sh (script: "ls -la ${workspace}/package", returnStatus: true /* don't throw exceptions if something goes wrong */) - } else { - echo ("Packaging skipped because the label 'skip-packages' was found") - } - } - - stage ('Nugetizing') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - def skipNugets = getLabels ().contains ("skip-nugets") - if (!skipNugets) { - sh ("${workspace}/xamarin-macios/jenkins/build-nugets.sh") - sh (script: "ls -la ${workspace}/package", returnStatus: true /* don't throw exceptions if something goes wrong */) - } else { - echo ("Nugetizing skipped because the label 'skip-nugets' was found") - } - } - - stage ('Signing') { - def entitlements = "${workspace}/xamarin-macios/mac-entitlements.plist" - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - def skipSigning = getLabels ().contains ("skip-signing") - if (!skipSigning) { - def xiPackages = findFiles (glob: "package/xamarin.ios-*.pkg") - if (xiPackages.length > 0) { - xiPackageFilename = xiPackages [0].name - echo ("Created Xamarin.iOS package: ${xiPackageFilename}") - } - def xmPackages = findFiles (glob: "package/xamarin.mac-*.pkg") - if (xmPackages.length > 0) { - xmPackageFilename = xmPackages [0].name - echo ("Created Xamarin.Mac package: ${xmPackageFilename}") - } - def msbuildZip = findFiles (glob: "package/msbuild.zip") - if (msbuildZip.length > 0) - msbuildZipFilename = msbuildZip [0].name - def bundleZip = findFiles (glob: "package/bundle.zip") - if (bundleZip.length > 0) - bundleZipFilename = bundleZip [0].name - - if (isPr) { - withCredentials ([string (credentialsId: 'codesign_keychain_pw', variable: 'PRODUCTSIGN_KEYCHAIN_PASSWORD')]) { - sh ("${workspace}/xamarin-macios/jenkins/productsign.sh") - } - } else { - try { - pkgs = xiPackages + xmPackages - if (fileExists('release-scripts')) { - dir('release-scripts') { - sh ('git checkout sign-and-notarized && git pull') - } - } else { - sh ('git clone git@github.com:xamarin/release-scripts -b sign-and-notarized') - } - withCredentials([string(credentialsId: 'codesign_keychain_pw', variable: 'KEYCHAIN_PASS'), string(credentialsId: 'team_id', variable: 'TEAM_ID'), string(credentialsId: 'application_id', variable: 'APP_ID'), string(credentialsId: 'installer_id', variable: 'INSTALL_ID'), usernamePassword(credentialsId: 'apple_account', passwordVariable: 'APPLE_PASS', usernameVariable: 'APPLE_ACCOUNT')]) { - sh (returnStatus: true, script: "security create-keychain -p ${env.KEYCHAIN_PASS} login.keychain") // needed to repopulate the keychain - sh ("security unlock-keychain -p ${env.KEYCHAIN_PASS} login.keychain") - timeout (time: 90, unit: 'MINUTES') { - sh ("python release-scripts/sign_and_notarize.py -a ${env.APP_ID} -i ${env.INSTALL_ID} -u ${env.APPLE_ACCOUNT} -p ${env.APPLE_PASS} -t ${env.TEAM_ID} -d package/notarized -e ${entitlements} -k login.keychain " + pkgs.flatten ().join (" ")) - } - } - - def xiNotarizedPackages = findFiles (glob: "package/notarized/xamarin.ios-*.pkg") - if (xiNotarizedPackages.length > 0) { - xiNotarizedPkgFilename = xiNotarizedPackages [0].name - echo ("Created notarized Xamarin.iOS package: ${xiNotarizedPkgFilename}") - } - def xmNotarizedPackages = findFiles (glob: "package/notarized/xamarin.mac-*.pkg") - if (xmNotarizedPackages.length > 0) { - xmNotarizedPkgFilename = xmNotarizedPackages [0].name - echo ("Created notarized Xamarin.Mac package: ${xmNotarizedPkgFilename}") - } - } catch (ex) { - echo "Notarization failed:\n${ex.getMessage()}" - for (def stack : ex.getStackTrace()) { - echo "\t${stack}" - } - manager.addWarningBadge("PKGs are not notarized") - } - } - } else { - echo ("Signing skipped because the label 'skip-signing' was found") - } - } - - stage ('Generate Workspace Info') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - withCredentials([string (credentialsId: '92cf81e5-6db5-408c-8a0d-192b36200a16', variable: 'GITHUB_AUTH_TOKEN'), string (credentialsId: 'xamarin-build-tasks', variable: 'XAMARIN_BUILD_TASKS')]) { - def redirect = getRedirect () - sh "curl -o Xamarin.Build.Tasks.nupkg \"${redirect}\"" - dir("BuildTasks") { - deleteDir () - sh "unzip ../Xamarin.Build.Tasks.nupkg" - sh "mono tools/BuildTasks/build-tasks.exe workspaceinfo -p ${workspace} -o ${workspace}/package-internal/ci-checkout.json" - sh "mono tools/BuildTasks/build-tasks.exe dependencyinfo -p ${workspace} -o ${workspace}/package-internal/dependency-info.json" - } - } - } - - stage ('Upload to Azure') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - virtualPath = "jenkins/${branchName}/${gitHash}/${env.BUILD_NUMBER}" - packagePrefix = "https://bosstoragemirror.blob.core.windows.net/wrench/${virtualPath}/package" - - // Create manifest - def uploadingFiles = findFiles (glob: "package/*") - def manifest = "" - for (int i = 0; i < uploadingFiles.length; i++) { - def file = uploadingFiles [i] - manifest += "${packagePrefix}/${file.name}\n" - } - manifest += "${packagePrefix}/artifacts.json\n" - manifest += "${packagePrefix}/manifest\n" - writeFile (file: "package/manifest", text: manifest) - - sh ("ls -la package") - uploadFiles ("package/*", "wrench", virtualPath) - - def notarized_files = findFiles (glob: "package/notarized/*") - if (notarized_files.size () > 0) - uploadFiles ("package/notarized/*", "wrench", virtualPath) - uploadFiles ("package-internal/*", "jenkins-internal", virtualPath) - - // Also upload manifest to a predictable url (without the build number) - // This manifest will be overwritten in subsequent builds (for this [PR/branch]+hash combination) - uploadFiles ("package/manifest", "wrench", "jenkins/${branchName}/${gitHash}") - // And also create a 'latest' version (which really means 'latest built', not 'latest hash', but it will hopefully be good enough) - uploadFiles ("package/manifest", "wrench", "jenkins/${branchName}/latest") - // And finally create a per-hash manifest (which will be overwritten in rebuilds of the same hash) - uploadFiles ("package/manifest", "wrench", "jenkins/${gitHash}") - - manifestFilename = "manifest" - } - - stage ('Generate artifacts.json') { - withCredentials ([string (credentialsId: '92cf81e5-6db5-408c-8a0d-192b36200a16', variable: 'GITHUB_AUTH_TOKEN'), usernamePassword (credentialsId: 'd146d4aa-a437-4633-908f-b455876c44d0', passwordVariable: 'STORAGE_PASSWORD', usernameVariable: 'STORAGE_ACCOUNT')]) { - dir ("BuildTasks") { - try { - sh "mono tools/BuildTasks/build-tasks.exe artifacts -s ${workspace}/xamarin-macios -a ${env.STORAGE_ACCOUNT} -c ${env.STORAGE_PASSWORD} -u wrench/${virtualPath}/package" - artifactsFilename = "artifacts.json" - } catch (err) { - def msg = "Failed to generate/upload artifacts.json: " + err.getMessage (); - echo ("⚠ī¸ ${msg} ⚠ī¸") - manager.addWarningBadge (msg) - appendFileComment ("⚠ī¸ [${msg}](${env.RUN_DISPLAY_URL}) đŸ”Ĩ\n") - } - } - } - } - - stage ('Publish builds to GitHub') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - utils = load ("${workspace}/xamarin-macios/jenkins/utils.groovy") - def packagesMessage = "" - if (xiPackageFilename != null) { - xiPackageUrl = "${packagePrefix}/${xiPackageFilename}" - utils.reportGitHubStatus (gitHash, 'PKG-Xamarin.iOS', "${xiPackageUrl}", 'SUCCESS', "${xiPackageFilename}") - packagesMessage += "* [${xiPackageFilename} (Not notarized)](${xiPackageUrl})\n" - } - if (xmPackageFilename != null) { - xmPackageUrl = "${packagePrefix}/${xmPackageFilename}" - utils.reportGitHubStatus (gitHash, 'PKG-Xamarin.Mac', "${xmPackageUrl}", 'SUCCESS', "${xmPackageFilename}") - packagesMessage += "* [${xmPackageFilename} (Not notarized)](${xmPackageUrl})\n" - } - if (xiNotarizedPkgFilename != null) { - xiNotarizedPackageUrl = "${packagePrefix}/notarized/${xiNotarizedPkgFilename}" - utils.reportGitHubStatus (gitHash, 'PKG-Xamarin.iOS-notarized', "${xiNotarizedPackageUrl}", 'SUCCESS', "${xiNotarizedPkgFilename}") - packagesMessage += "* [${xiNotarizedPkgFilename} (Notarized)](${xiNotarizedPackageUrl})\n" - } - if (xmNotarizedPkgFilename != null) { - xmNotarizedPackageUrl = "${packagePrefix}/notarized/${xmNotarizedPkgFilename}" - utils.reportGitHubStatus (gitHash, 'PKG-Xamarin.Mac-notarized', "${xmNotarizedPackageUrl}", 'SUCCESS', "${xmNotarizedPkgFilename}") - packagesMessage += "* [${xmNotarizedPkgFilename} (Notarized)](${xmNotarizedPackageUrl})\n" - } - if (manifestFilename != null) { - def manifestUrl = "${packagePrefix}/${manifestFilename}" - utils.reportGitHubStatus (gitHash, "${manifestFilename}", "${manifestUrl}", 'SUCCESS', "${manifestFilename}") - } - if (artifactsFilename != null) { - def artifactUrl = "${packagePrefix}/${artifactsFilename}" - utils.reportGitHubStatus (gitHash, "Jenkins: Artifacts", "${artifactUrl}", 'SUCCESS', "${artifactsFilename}") - } - if (bundleZipFilename != null) { - def bundleZipUrl = "${packagePrefix}/${bundleZipFilename}" - utils.reportGitHubStatus (gitHash, "bundle.zip", "${bundleZipUrl}", 'SUCCESS', "${bundleZipFilename}") - } - if (msbuildZipFilename != null) { - def msbuildZipUrl = "${packagePrefix}/${msbuildZipFilename}" - utils.reportGitHubStatus (gitHash, "msbuild.zip", "${msbuildZipUrl}", 'SUCCESS', "${msbuildZipFilename}") - } - - def nupkgs = findFiles (glob: "package/*.nupkg") - for (def i = 0; i < nupkgs.size (); i++) { - def nupkg = nupkgs [i] - def nupkg_name = nupkg.name - def nupkgUrl = "${packagePrefix}/${nupkg_name}" - utils.reportGitHubStatus (gitHash, nupkg_name, nupkgUrl, "SUCCESS", nupkg_name) - packagesMessage += "* [${nupkg_name}](${nupkgUrl})\n" - } - - // Publish any other *.pkg files we've created - def pkgs = findFiles (glob: "package/*.pkg") - pkgs += findFiles (glob: "package/*.msi") - for (def i = 0; i < pkgs.size (); i++) { - def pkg = pkgs [i]; - def pkg_name = pkg.name - if (pkg_name == xiPackageFilename || pkg_name == xmPackageFilename) - continue // we've already handled these files - def pkgUrl = "${packagePrefix}/${pkg_name}" - utils.reportGitHubStatus (gitHash, pkg_name, pkgUrl, "SUCCESS", pkg_name) - packagesMessage += "* [${pkg_name}](${pkgUrl})\n" - } - - if (packagesMessage != "") - appendFileComment ("✅ Packages built successfully\n
View packages\n\n${packagesMessage}\n
\n\n") - } - - stage ('Publish Nugets') { - currentStage = "${STAGE_NAME}" - withCredentials ([string (credentialsId: 'azdo-package-feed-token', variable: 'AZDO_PACKAGE_FEED_TOKEN')]) { - def nupkgs = findFiles (glob: "package/notarized/*") - if (nupkgs.size () == 0) { - echo ("No NuGet packages to publish.") - } else { - def nugetResult = sh (script: "${workspace}/xamarin-macios/jenkins/publish-to-nuget.sh --apikey=${AZDO_PACKAGE_FEED_TOKEN} --source=https://pkgs.dev.azure.com/azure-public/vside/_packaging/xamarin-impl/nuget/v3/index.json package/*.nupkg", returnStatus: true) - if (nugetResult != 0) { - failedStages.add (currentStage) - manualException = true - def msg = "Failed to publish NuGet packages. Please review log for details." - echo ("⚠ī¸ ${msg} ⚠ī¸") - manager.addWarningBadge (msg) - appendFileComment ("⚠ī¸ [${msg}](${env.RUN_DISPLAY_URL}) đŸ”Ĩ\n") - } else { - echo ("${currentStage} succeeded") - } - } - } - } - - dir ('xamarin-macios') { - stage ('Launch external tests') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - // VSTS does not allow any branch name anymore, it has to be an existing branch. - // Since pull requests don't create branches in the xamarin org (that VSTS sees at least), - // I've created a 'pull-request' branch which we'll use for pull requests. - def vsts_branch = isPr ? "pull-request" : branchName; - def skipExternalTests = getLabels ().contains ("skip-external-tests") - if (skipExternalTests) { - echo ("Skipping external tests because the label 'skip-external-tests' was found") - } else if (isPr && !getLabels ().contains ("trigger-device-tests")) { - echo ("Skipping external tests because the label 'trigger-device-tests' was not found and it's required for external tests to run for pull requests") - } else { - def outputFile = "${workspace}/xamarin-macios/wrench-launch-external.output.tmp" - try { - withCredentials ([string (credentialsId: 'macios_provisionator_pat', variable: 'PROVISIONATOR_VSTS_PAT'), string (credentialsId: 'macios_github_comment_token', variable: 'GITHUB_PAT_TOKEN')]) { - sh ("make -C ${workspace}/xamarin-macios/tests wrench-launch-external MAC_PACKAGE_URL=${xmPackageUrl} IOS_PACKAGE_URL=${xiPackageUrl} WRENCH_URL=${env.RUN_DISPLAY_URL} BUILD_REVISION=${gitHash} BUILD_LANE=${vsts_branch} BUILD_WORK_HOST=${env.NODE_NAME} GITHUB_TOKEN=${GITHUB_PAT_TOKEN} 2>&1 | tee ${outputFile}") - } - processAtMonkeyWrench (outputFile) - } catch (error) { - echo ("đŸšĢ Launching external tests failed: ${error} đŸšĢ") - manager.addWarningBadge ("Failed to launch external tests") - } finally { - sh ("rm -f '${outputFile}'") - } - } - - if (getLabels ().contains ("run-sample-tests")) { - def outputFile = "${workspace}/xamarin-macios/wrench-launch-external.output.tmp" - try { - withCredentials ([string (credentialsId: 'macios_provisionator_pat', variable: 'PROVISIONATOR_VSTS_PAT')]) { - sh ("make -C ${workspace}/maccore/tests/external wrench-launch-sample-builds 'BUILD_REVISION=${gitHash}' 'BUILD_BRANCH=${vsts_branch}' V=1 2>&1 | tee ${outputFile}") - } - processAtMonkeyWrench (outputFile) - } catch (error) { - echo ("đŸšĢ Launching external sample tests failed: ${error} đŸšĢ") - manager.addWarningBadge ("Failed to launch external sample tests") - } finally { - sh ("rm -f '${outputFile}'") - } - } - } - - stage ('Install Provisioning Profiles') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - withCredentials ([string (credentialsId: 'login-keychain-password', variable: "LOGIN_KEYCHAIN_PASSWORD")]) { - sh ("${workspace}/maccore/tools/install-qa-provisioning-profiles.sh") - } - } - - stage ('Publish reports') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - reportPrefix = sh (script: "${workspace}/xamarin-macios/jenkins/publish-results.sh | grep '^Url Prefix: ' | sed 's/^Url Prefix: //'", returnStdout: true).trim () - if (skipLocalTestRunReason == "") { - echo ("Html report: ${reportPrefix}/tests/index.html") - } else { - echo ("Html report: ${skipLocalTestRunReason}") - } - echo ("API diff (from stable): ${reportPrefix}/api-diff/index.html") - echo ("API diff (from previous commit / before pull request): ${reportPrefix}/apicomparison/api-diff.html") - echo ("Generator diff: ${reportPrefix}/generator-diff/index.html") - } - - stage ('API diff') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - def apidiffResult = sh (script: "${workspace}/xamarin-macios/jenkins/build-api-diff.sh --publish", returnStatus: true) - if (apidiffResult != 0) - manager.addWarningBadge ("Failed to generate API diff") - echo ("API diff (from stable): ${reportPrefix}/api-diff/index.html") - } - - stage ('API & Generator comparison') { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - def compareResult = sh (script: "${workspace}/xamarin-macios/jenkins/compare.sh --publish", returnStatus: true) - if (compareResult != 0) - manager.addWarningBadge ("Failed to generate API / Generator diff") - echo ("API diff (from previous commit / before pull request): ${reportPrefix}/apicomparison/api-diff.html") - echo ("Generator diff: ${reportPrefix}/generator-diff/index.html") - } - - def hasXamarinMacTests = true - stage ("Package XM tests") { - currentStage = "${STAGE_NAME}" - echo ("Building on ${env.NODE_NAME}") - def skipPackagedXamarinMacTests = getLabels ().contains ("skip-packaged-xamarin-mac-tests") - if (skipPackagedXamarinMacTests) { - echo ("Skipping packaged Xamarin.Mac tests because the label 'skip-packaged-xamarin-mac-tests' was found") - hasXamarinMacTests = false - } else { - def exitCode = sh (script: "make -C ${workspace}/xamarin-macios/tests package-tests", returnStatus: true) - if (exitCode != 0) { - hasXamarinMacTests = false - echoError ("Failed to package Xamarin.Mac tests (exit code: ${exitCode})") - failedStages.add (currentStage) - } else { - def packaged_xm_tests = findFiles (glob: "tests/*.7z") - if (packaged_xm_tests.size () > 0) { - uploadFiles ("tests/*.7z", "wrench", virtualPath) - } else { - // This may happen if the Xamarin.Mac build has been disabled - manager.addWarningBadge("Could not find any packaged Xamarin.Mac tests to upload") - hasXamarinMacTests = false - } - } - } - } - - timeout (time: 13, unit: 'HOURS') { - // We run tests locally and on older macOS bots in parallel. - // The older macOS tests run quickly (and the bots should usually be idle), - // which means that the much longer normal (local) test run should take - // longer to complete (which is important since this will block until all tests - // have been run, even if any older macOS bots are busy doing other things, preventing - // our tests from running there), giving the older macOS bots plenty of - // time to finish their test runs. - stage ('Run tests parallelized') { - def builders = [:] - - // Add test runs on older macOS versions - if (hasXamarinMacTests) { - def url = "https://bosstoragemirror.blob.core.windows.net/wrench/${virtualPath}/tests/mac-test-package.7z" - def maccore_hash = sh (script: "grep NEEDED_MACCORE_VERSION ${workspace}/xamarin-macios/mk/xamarin.mk | sed 's/NEEDED_MACCORE_VERSION := //'", returnStdout: true).trim () - // Get the min and current macOS version from Make.config, - // and calculate all the macOS versions in between (including both end points). - // The trims/splits/toIntegers at the end are to select the minor part of the macOS version number, - // then we just loop from the minor part of the min version to the minor part of the current version. - def firstOS = sh (returnStdout: true, script: "grep ^MIN_MACOS_SDK_VERSION= '${workspace}/xamarin-macios/Make.config' | sed 's/.*=//'").trim ().split ("\\.")[1].toInteger () - def lastOS = sh (returnStdout: true, script: "grep ^MACOS_NUGET_VERSION= '${workspace}/xamarin-macios/Make.versions' | sed -e 's/.*=//' -e 's/.[0-9]*\$//'").trim ().split ("\\.")[1].toInteger () - def macOSes = [] - def excludedOSes = [] - // If any macOS version needs to be excluded manually, it can be done like this (in this case to remove macOS 10.14): - // Any macOS versions excluded like this still get a entry in the Jenkins UI, making it explicit that the OS version was skipped. - // excludedOSes.add ("10.14") - excludedOSes.add ("11.0") // We have a bot labelled as 10.16 (and we're running there) - // Have in mind that the value in the list is only the minor part of the macOS version number. - for (i = 0; i < macOSes.size (); i++) { - def os = macOSes [i]; - def macOS = "${os}" // Need to bind the label variable before the closure - def excluded = false - def nodeText = "XM tests on ${macOS}" - if (indexOfElement (excludedOSes, os) >= 0) { - excluded = true - nodeText = "ℹī¸ XM tests not executed on ${macOS} ℹī¸" - } else if (os == mainMacOSVersion) { - excluded = true - nodeText = "ℹī¸ XM tests not executed on a separate ${macOS} bot because they're already executed as a part of the main test run ℹī¸" - } - builders [nodeText] = { - try { - timeout (time: 15, unit: 'MINUTES') { - if (excluded) { - echo (nodeText) - } else { - node ("xamarin-macios && macos-10.${macOS}") { - stage ("Running XM tests on '10.${macOS}'") { - runXamarinMacTests (url, "macOS 10.${macOS}", maccore_hash, gitHash) - } - } - } - } - } catch (err) { - currentStage = "Running XM tests on '${macOS}'" - def msg = "Xamarin.Mac tests on ${macOS} failed: " + err.getMessage (); - appendFileComment ("đŸ”Ĩ [${msg}](${env.RUN_DISPLAY_URL}) đŸ”Ĩ\n") - failedStages.add (currentStage) - throw err - } - } - } - } - - // Add standard test run - builders ["All tests"] = { - stage ('Run tests') { - currentStage = "Test run" - echo ("Building on ${env.NODE_NAME}") - if (skipLocalTestRunReason != "") { - echo (skipLocalTestRunReason) - appendFileComment ("ℹī¸ Test run skipped: ${skipLocalTestRunReason}\n") - } else { - def XHARNESS_GITHUB_TOKEN_FILE = "${workspace}/xamarin-macios/jenkins/.github-pat-token" - withCredentials ([string (credentialsId: 'macios_github_comment_token', variable: 'GITHUB_PAT_TOKEN')]) { - writeFile (file: "${XHARNESS_GITHUB_TOKEN_FILE}", text: "${GITHUB_PAT_TOKEN}") - } - echo ("Html report: ${reportPrefix}/tests/index.html") - def runTestResult = null - withEnv (["XHARNESS_GITHUB_TOKEN_FILE=${XHARNESS_GITHUB_TOKEN_FILE}"]) { - runTestResult = sh (script: "${workspace}/xamarin-macios/jenkins/run-tests.sh --target=wrench-jenkins --publish --keychain=xamarin-macios", returnStatus: true) - } - if (runTestResult != 0) { - failedStages.add (currentStage) - manualException = true - error ("Test run failed: ${reportPrefix}/tests/index.html") - } else { - echo ("${currentStage} succeeded") - } - } - } - } - - // Run it all parallelized - parallel builders - } - } - - currentStage = "" - } // dir ("xamarin-macios") - } // dir ("${workspace}") - } - reportFinalStatus ("", "${gitHash}", "${currentStage}") - } // timeout - } catch (err) { - timeout (time: 5, unit: 'MINUTES') { // Give 5 minutes to publish results to GitHub/Slack - reportFinalStatus ("${err}", "${gitHash}", "${currentStage}") - } // timeout - } finally { - timeout (time: 60, unit: 'MINUTES') { // Give an hour to publish and upload stuff - stage ('Final tasks') { - sh (script: "${workspace}/xamarin-macios/jenkins/publish-results.sh", returnStatus: true /* don't throw exceptions if something goes wrong */) - sh (script: "make git-clean-all -C ${workspace}/xamarin-macios", returnStatus: true /* don't throw exceptions if something goes wrong */) - } - } // timeout - } // try - } // node -} // timestamps diff --git a/jenkins/Makefile b/jenkins/Makefile deleted file mode 100644 index be90463cb8..0000000000 --- a/jenkins/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -TOP=.. -include $(TOP)/Make.config - -all check: - shellcheck *.sh - -print-abspath-variable: - @echo $(VARIABLE)=$(abspath $($(VARIABLE))) diff --git a/jenkins/README.md b/jenkins/README.md deleted file mode 100644 index 8eb5792600..0000000000 --- a/jenkins/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Jenkins - -This directory contains all the scripts to be executed as steps in the jenkins build bots for each of the PR in the project. The expected order in which they have to -be executed is as follows: - -* provision-deps.sh : Downloads and installs the project dependencies. -* build.sh : Builds the project. -* run-tests.sh : Runs the tests. -* build-api-diff.sh : Builds the API diff. - -# Jenkinsfile - -This file contains the logic to run on our internal Jenkins, available here: http://xamarin-jenkins/blue/organizations/jenkins/macios/activity - -The Jenkins job is a multi-branch pipeline job, it will execute in the -following conditions: - -* For all branches in the xamarin org (not forks) that has a - jenkins/Jenkinsfile file. -* For all pull requests from people with write access (also conditional on - having a jenkins/Jenkinsfile file). - -In very broad strokes, the Jenkins job will: - -* Checkout xamarin-macios -* Build -* Create packages, upload them to Azure and publish the links to the packages - as GitHub statuses. -* Run our test suite. -* Run selected Xamarin.Mac tests on all macOS versions we support. This is - done in parallel with the normal test run. - - If a particular macOS version must be excluded temporarily from testing, - search Jenkinsfile for `excludedOSes` and follow the instructions you'll - find. diff --git a/jenkins/build-api-diff.sh b/jenkins/build-api-diff.sh deleted file mode 100755 index f3b83f854c..0000000000 --- a/jenkins/build-api-diff.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -e - -cd "$(dirname "${BASH_SOURCE[0]}")/.." -WORKSPACE=$(pwd) - -report_error () -{ - printf "đŸ”Ĩ [Failed to create API Diff](%s/console) đŸ”Ĩ\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" -} -trap report_error ERR - -# SC2154: ghprbPullId is referenced but not assigned. -# shellcheck disable=SC2154 -if test -n "$ghprbPullId" && ./jenkins/fetch-pr-labels.sh --check=skip-public-jenkins; then - echo "Skipping API diff because the label 'skip-public-jenkins' was found." - exit 0 -fi - -export BUILD_REVISION=jenkins -make -j8 -C tools/apidiff jenkins-api-diff - -if [[ "x$1" == "x--publish" ]]; then - URL_PREFIX=$(./jenkins/publish-results.sh | grep "^Url Prefix: " | sed 's/^Url Prefix: //') - URL="$URL_PREFIX/api-diff/index.html" -else - URL="$BUILD_URL/API_20diff_20_28from_20stable_29" -fi - -printf "✅ [API Diff (from stable)](%s)\\n" "$URL" >> "$WORKSPACE/jenkins/pr-comments.md" diff --git a/jenkins/build.sh b/jenkins/build.sh deleted file mode 100755 index 20b4dbadc6..0000000000 --- a/jenkins/build.sh +++ /dev/null @@ -1,140 +0,0 @@ -#!/bin/bash -e - -# Script that builds xamarin-macios for CI -# -# --configure-flags=: Flags to pass to --configure. Optional -# --timeout=: Time out the build after seconds. - -cd "$(dirname "${BASH_SOURCE[0]}")/.." -WORKSPACE=$(pwd) - -export FAILURE_REASON_PATH="$WORKSPACE/jenkins/build-failure.md" - -report_error () -{ - printf "đŸ”Ĩ [Build failed](%s/console) đŸ”Ĩ\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" - if test -f "$FAILURE_REASON_PATH"; then - sed 's/^/* /' "$FAILURE_REASON_PATH" >> "$WORKSPACE/jenkins/pr-comments.md" - fi -} -trap report_error ERR - -timeout () -{ - # create a subprocess that kills this process after a certain number of seconds - SELF_PID=$$ - ( - sleep "$1" - echo "Execution timed out after $1 seconds." - printf "❌ [Build timed out](%s/console)\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" - kill -9 $SELF_PID - )& - # kill the subprocess timeout if we exit before we time out - TIMEOUT_PID=$! - trap 'kill -9 $TIMEOUT_PID' EXIT -} - -while ! test -z "$1"; do - case "$1" in - --configure-flags=*) - CONFIGURE_FLAGS="${1#*=}" - shift - ;; - --configure-flags) - CONFIGURE_FLAGS="$2" - shift 2 - ;; - --timeout=*) - TIMEOUT="${1#*=}" - shift - ;; - --timeout) - TIMEOUT="$2" - shift 2 - ;; - *) - echo "Unknown argument: $1" - exit 1 - ;; - esac -done - -if test -n "$TIMEOUT"; then - timeout "$TIMEOUT" -fi - -ls -la "$WORKSPACE/jenkins" -echo "$WORKSPACE/jenkins/pr-comments.md:" -cat "$WORKSPACE/jenkins/pr-comments.md" || true - -export BUILD_REVISION=jenkins - -ENABLE_DEVICE_BUILD= - -# SC2154: ghprbPullId is referenced but not assigned. -# shellcheck disable=SC2154 -if test -z "$ghprbPullId"; then - echo "Could not find the environment variable ghprbPullId, so forcing a device build." - ENABLE_DEVICE_BUILD=1 -else - if ./jenkins/fetch-pr-labels.sh --check=skip-public-jenkins; then - echo "Skipping execution because the label 'skip-public-jenkins' was found." - printf "ℹī¸ [Skipped execution](%s/console)\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" - exit 0 - fi - echo "Listing modified files for pull request #$ghprbPullId..." - if git diff-tree --no-commit-id --name-only -r "origin/pr/$ghprbPullId/merge^..origin/pr/$ghprbPullId/merge" > .tmp-files; then - echo "Modified files found": - sed 's/^/ /' .tmp-files || true - if grep 'mk/mono.mk' .tmp-files > /dev/null; then - echo "Enabling device build because mono was bumped." - ENABLE_DEVICE_BUILD=1 - else - echo "Not enabling device build; mono wasn't bumped." - fi - fi - rm -f .tmp-files - - if test -z "$ENABLE_DEVICE_BUILD"; then - if ./jenkins/fetch-pr-labels.sh --check=enable-device-build; then - ENABLE_DEVICE_BUILD=1 - echo "Enabling device build because the label 'enable-device-build' was found." - else - echo "Not enabling device build; no label named 'enable-device-build' was found." - fi - fi - - if ./jenkins/fetch-pr-labels.sh --check=run-sample-tests; then - echo "The sample tests won't be triggered from public jenkins even if the 'run-sample-tests' label is set (build on internal Jenkins instead)." - printf "ℹī¸ The sample tests won't be triggered from public jenkins even if the 'run-sample-tests' label is set (build on internal Jenkins instead).\\n" >> "$WORKSPACE/jenkins/pr-comments.md" - fi - - if ./jenkins/fetch-pr-labels.sh --check=disable-packaged-mono; then - echo "Building mono from source because the label 'disable-packaged-mono' was found." - CONFIGURE_FLAGS="$CONFIGURE_FLAGS --disable-packaged-mono" - fi -fi - - -if test -z "$ENABLE_DEVICE_BUILD"; then - CONFIGURE_FLAGS="$CONFIGURE_FLAGS --disable-ios-device" -fi - -# Enable dotnet bits on the bots -CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-dotnet --enable-install-source" - -echo "Configuring the build with: $CONFIGURE_FLAGS" -# shellcheck disable=SC2086 -./configure $CONFIGURE_FLAGS - -# If we're building mono from source, we might not have it cloned yet -make reset - -time make -j8 -time make install -j8 - -printf "✅ [Build succeeded](%s/console)\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" - -if grep MONO_BUILD_FROM_SOURCE=. configure.inc Make.config.inc >& /dev/null; then - printf " ⚠ī¸ Mono built from source\\n" >> "$WORKSPACE/jenkins/pr-comments.md" -fi diff --git a/jenkins/fetch-pr-labels.sh b/jenkins/fetch-pr-labels.sh deleted file mode 100755 index 6c4f051050..0000000000 --- a/jenkins/fetch-pr-labels.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash -e - -# SC2154: ghprbPullId is referenced but not assigned. -# shellcheck disable=SC2154 -if test -z "$ghprbPullId"; then - echo "Could not find the environment variable ghprbPullId, so it's not possible to fetch the labels for any pull request." - exit 1 -fi - -FORCE= -CHECK= -while ! test -z "$1"; do - case "$1" in - --force|-f) - FORCE=1 - shift - ;; - --check) - if test -z "$2"; then - echo "Missing argument to --check" - exit 1 - fi - CHECK="$2" - shift 2 - ;; - --check=*|--check:*) - CHECK="${1:8}" - shift - ;; - *) - echo "Unknown argument: $1" - exit 1 - ;; - esac -done - -cd "$(dirname "$0")" - -TMPFILE=".tmp-labels-$ghprbPullId" -if [[ x"$FORCE" == "x" && ( -f "$TMPFILE" ) ]]; then - echo "Not downloading labels for pull request #$ghprbPullId because they've already been downloaded." -else - echo "Downloading labels for pull request #$ghprbPullId..." - if ! curl --silent "https://api.github.com/repos/xamarin/xamarin-macios/issues/$ghprbPullId/labels" > "$TMPFILE.dl"; then - echo "Failed to fetch labels for the pull request $ghprbPullId." - exit 1 - fi - grep "\"name\":" "$TMPFILE.dl" | sed -e 's/name": \"//' -e 's/.*\"\(.*\)\".*/\1/'> "$TMPFILE" || true -fi - -# Find any custom labels -grep -v '^[[:space:]]*#' custom-labels.txt | grep -v '^[[:space:]]*$' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' >> "$TMPFILE" || true - -if test -z "$CHECK"; then - echo "Labels found:" - sed 's/^/ /' "$TMPFILE" -else - if grep "^$CHECK$" "$TMPFILE" >/dev/null 2>&1; then - echo "The pull request $ghprbPullId contains the label $CHECK." - else - echo "The pull request $ghprbPullId does not contain the label $CHECK." - exit 1 - fi -fi diff --git a/jenkins/list-macos-platforms.csharp b/jenkins/list-macos-platforms.csharp deleted file mode 100755 index dc1b45f2b1..0000000000 --- a/jenkins/list-macos-platforms.csharp +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env /Library/Frameworks/Mono.framework/Commands/csharp - -using System.IO; -using System.Text; -using System.Xml; - -var args = Environment.GetCommandLineArgs (); -var expectedArgumentCount = 1; -if (args.Length != expectedArgumentCount + 2 /* 2 default arguments (executable + script) + 'expectedArgumentCount' arguments we're interested in */) { - // first arg is "/Library/Frameworks/Mono.framework/Versions/4.8.0/lib/mono/4.5/csharp.exe" - // second arg the script itself - // then comes the ones we care about - Console.WriteLine ($"Need {expectedArgumentCount} arguments, got {args.Length - 2}"); - Environment.Exit (1); - return; -} - -var plistPath = args [2]; -var doc = new XmlDocument (); -doc.Load (plistPath); -var nodes = doc.SelectNodes ($"/plist/dict/key[text()='KnownVersions']/following-sibling::dict[1]/key[text()='macOS']/following-sibling::array[1]/string"); - -var sb = new StringBuilder (); -foreach (XmlNode n in nodes) - sb.Append ($"{n.InnerText} "); -Console.WriteLine (sb); - -Environment.Exit (0); diff --git a/jenkins/prepare-packaged-macos-tests.sh b/jenkins/prepare-packaged-macos-tests.sh deleted file mode 100755 index dd499af08f..0000000000 --- a/jenkins/prepare-packaged-macos-tests.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash -e - -# don't change the current directory here - -if [[ "$1" == "--install-old-mono" ]]; then - cd mac-test-package - URL=$(grep "^MIN_XM_MONO_URL=" Make.config | sed 's/.*=//') - - COUNTER=0 - echo "Downloading and installing $URL" - while [[ $COUNTER -lt 5 ]]; do - EC=0 - curl -s -L "$URL" --output old-mono.pkg || EC=$? - if [[ $EC -eq 56 ]]; then - # Sometimes we get spurious "curl: (56) SSLRead() return error -9806" errors. Trying again usually works, so lets try again a few more times. - # https://github.com/xamarin/maccore/issues/1098 - let COUNTER++ || true - continue - fi - break - done - - if [[ "x$EC" != "x0" ]]; then - echo "Failed to provision old mono (exit code: $EC)" - exit $EC - fi - - sudo installer -pkg old-mono.pkg -target / - mono --version - exit 0 -fi - - -URL=$1 -MACCORE_HASH=$2 -if test -z "$URL"; then - echo "First argument must be the url for the packaged mac tests." - exit 1 -fi -if test -z "$MACCORE_HASH"; then - echo "Second argument must be the maccore hash." - exit 1 -fi - -# Allow some bot-specific configuration. -# Some bots use this to change PATH to where a custom version of ruby is installed. -if test -f ~/.jenkins-profile; then - # SC1090: Can't follow non-constant source. Use a directive to specify location. - # shellcheck disable=SC1090 - source ~/.jenkins-profile; -fi - -# Install 7z. We can't do this from the system-dependencies.sh script, because -# we need 7z to decompress the file where the system-dependencies.sh script -# resides. -# Also ignore any failures, brew may fail if 7z is already installed. -brew install p7zip || true - -env -rm -f -- ./*.7z -curl -fL "$URL" --output mac-test-package.7z -rm -rf mac-test-package -7z x mac-test-package.7z -cd mac-test-package - -COUNTER=0 -while [[ $COUNTER -lt 5 ]]; do - EC=0 - ./system-dependencies.sh --ignore-all --provision-mono || EC=$? - if [[ $EC -eq 56 ]]; then - # Sometimes we get spurious "curl: (56) SSLRead() return error -9806" errors. Trying again usually works, so lets try again a few more times. - # https://github.com/xamarin/maccore/issues/1098 - let COUNTER++ || true - continue - fi - break -done - -if [[ "x$EC" != "x0" ]]; then - echo "Failed to provision dependencies (exit code: $EC)" - exit $EC -fi - -# fetch script to install provisioning profiles and run it -if test -d maccore; then - cd maccore - if ! git fetch origin; then - cd .. - rm -Rf maccore - fi -fi -if ! test -d maccore; then - git clone git@github.com:xamarin/maccore - cd maccore -fi -git reset --hard "$MACCORE_HASH" -cd .. - -./maccore/tools/install-qa-provisioning-profiles.sh --only-create-keychain -v diff --git a/jenkins/provision-deps.sh b/jenkins/provision-deps.sh deleted file mode 100755 index 3e82769e45..0000000000 --- a/jenkins/provision-deps.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -e - -cd "$(dirname "${BASH_SOURCE[0]}")/.." -WORKSPACE=$(pwd) - -report_error () -{ - echo "đŸ”Ĩ [Provisioning failed]($BUILD_URL/console) đŸ”Ĩ" >> "$WORKSPACE/jenkins/pr-comments.md" -} -trap report_error ERR - -# SC2154: ghprbPullId is referenced but not assigned. -# shellcheck disable=SC2154 -if test -n "$ghprbPullId" && ./jenkins/fetch-pr-labels.sh --check=skip-public-jenkins; then - echo "Skipping provisioning diff because the label 'skip-public-jenkins' was found." - exit 0 -fi - -# Get all our dependencies -make reset - -# Make sure everything is pristine -make git-clean-all - -# Print a list of our dpendencies -make print-versions - -# Provision external dependencies -./system-dependencies.sh --provision-all - -sudo rm -Rf /Developer/MonoTouch -sudo rm -Rf /Library/Frameworks/Xamarin.iOS.framework -sudo rm -Rf /Library/Frameworks/Xamarin.Mac.framework - -echo "✅ [Provisioning succeeded]($BUILD_URL/console)" >> "$WORKSPACE/jenkins/pr-comments.md" diff --git a/jenkins/publish-results.sh b/jenkins/publish-results.sh deleted file mode 100755 index f50df42039..0000000000 --- a/jenkins/publish-results.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -ex - -cd "$(dirname "${BASH_SOURCE[0]}")/.." -WORKSPACE=$(pwd) - -report_error () -{ - printf "đŸ”Ĩ [Failed to publish results](%s/console) đŸ”Ĩ\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" -} -trap report_error ERR - -# SC2154: ghprbPullId is referenced but not assigned. -# shellcheck disable=SC2154 -if test -n "$ghprbPullId"; then - BRANCH_NAME="pr$ghprbPullId" -elif test -z "$BRANCH_NAME"; then - echo "Neither BRANCH_NAME nor ghprbPullId is set" - exit 1 -fi -if test -z "$BUILD_NUMBER"; then - echo "BUILD_NUMBER is not set" - exit 1 -fi -P="jenkins/xamarin-macios/${BRANCH_NAME}/$(git log -1 --pretty=%H)/${BUILD_NUMBER}" - -echo "Url Prefix: http://xamarin-storage/$P/jenkins-results" -echo "Periodic Command: --periodic-interval 10 --periodic-command rsync --periodic-command-arguments '-avz --chmod=+r -e ssh $WORKSPACE/jenkins-results builder@xamarin-storage:/volume1/storage/$P'" - -mkdir -p "$WORKSPACE/jenkins-results" - -# Publish - -# Make sure the target directory exists - -# SC2029: Note that, unescaped, this expands on the client side. [Referring to $P] -# shellcheck disable=SC2029 -ssh builder@xamarin-storage "mkdir -p /volume1/storage/$P" -rsync -avz --chmod=+r -e ssh "$WORKSPACE/jenkins-results" "builder@xamarin-storage:/volume1/storage/$P" diff --git a/jenkins/publish-to-nuget.sh b/jenkins/publish-to-nuget.sh deleted file mode 100755 index 8e01e97e08..0000000000 --- a/jenkins/publish-to-nuget.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash -e - -# Script to publish nugets. -# -# Arguments (all required): -# --apikey=: The api key to authenticate with the nuget server. -# --source=: The nuget server -# - -INITIAL_CD=$(pwd) - -cd "$(dirname "${BASH_SOURCE[0]}")/.." -WORKSPACE=$(pwd) - -CONFIG_FILE=.nuget.config.tmp - -report_error () -{ - # remove config - rm -f $CONFIG_FILE - - # Show error - printf "đŸ”Ĩ [Failed to publish to nuget](%s/console) đŸ”Ĩ\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" -} -trap report_error ERR - -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$INITIAL_CD/${1#./}" -} - -APIKEY= -SOURCE= -VERBOSITY=() -NUGETS=() - -while ! test -z "${1:-}"; do - case "$1" in - --apikey=*) - APIKEY="${1:9}" - shift - ;; - --apikey) - APIKEY="$2" - shift 2 - ;; - --source=*) - SOURCE="${1:9}" - shift - ;; - --source) - SOURCE="$2" - shift 2 - ;; - -v | --verbose) - VERBOSITY=("-Verbosity" "detailed") - set -x - shift - ;; - -*) - echo "Unknown argument: $1" - exit 1 - ;; - *) - NUGETS+=("$1") - shift - ;; - esac -done - -if test -z "$APIKEY"; then - echo "The API key is required (--apikey=)" - exit 1 -fi - -if test -z "$SOURCE"; then - echo "The source is required (--source=)" - exit 1 -fi - -if [[ "x${#NUGETS[@]}" == "x0" ]]; then - echo "No nupkgs provided." - exit 1 -fi - -# create empty config for auth -echo '' > $CONFIG_FILE - -# add the feed -nuget sources add -name FEEDME -source "$SOURCE" -username WHATEVER -password "$APIKEY" -config $CONFIG_FILE - -# push -for nuget in "${NUGETS[@]}"; do - nuget="$(realpath "$nuget")" - nuget push "$nuget" -Source FEEDME -ApiKey WHATEVER -NonInteractive "${VERBOSITY[@]}" -ConfigFile $CONFIG_FILE -done - -# remove config -rm -f $CONFIG_FILE diff --git a/jenkins/run-tests.sh b/jenkins/run-tests.sh deleted file mode 100755 index b1e087a6b5..0000000000 --- a/jenkins/run-tests.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/bash -e - -cd "$(dirname "${BASH_SOURCE[0]}")/.." -WORKSPACE=$(pwd) - -# Print out environment for debug purposes -env | sort - -report_error () -{ - printf "đŸ”Ĩ [Test run failed](%s) đŸ”Ĩ\\n" "$URL" >> "$WORKSPACE/jenkins/pr-comments.md" - - if test -f "$WORKSPACE/tests/TestSummary.md"; then - printf "\\n" >> "$WORKSPACE/jenkins/pr-comments.md" - cat "$WORKSPACE/tests/TestSummary.md" >> "$WORKSPACE/jenkins/pr-comments.md" - fi - - touch "$WORKSPACE/jenkins/failure-stamp" -} -trap report_error ERR - -# SC2154: ghprbPullId is referenced but not assigned. -# shellcheck disable=SC2154 -if test -n "$ghprbPullId" && ./jenkins/fetch-pr-labels.sh --check=skip-public-jenkins; then - echo "Skipping tests because the label 'skip-public-jenkins' was found." - exit 0 -fi - -TARGET=jenkins -PUBLISH= -KEYCHAIN=builder -KEYCHAIN_PWD_FILE=~/.config/keychain -while ! test -z "$1"; do - case "$1" in - --target=*) - TARGET="${1:9}" - shift - ;; - --keychain=*) - KEYCHAIN="${1:11}" - KEYCHAIN_PWD_FILE=~/.config/$KEYCHAIN-keychain - shift - ;; - --publish) - PUBLISH=1 - shift - ;; - *) - echo "Unknown argument: $1" - exit 1 - ;; - esac -done - -if test -n "$PUBLISH"; then - PUBLISH_OUTPUT=$(./jenkins/publish-results.sh) - URL_PREFIX=$(echo "$PUBLISH_OUTPUT" | grep "^Url Prefix: " | sed 's/^Url Prefix: //') - URL="$URL_PREFIX/tests/index.html" - TESTS_PERIODIC_COMMAND=$(echo "$PUBLISH_OUTPUT" | grep "^Periodic Command: " | sed 's/^Periodic Command: //') - export TESTS_PERIODIC_COMMAND -else - URL="$BUILD_URL/Test_20Report" -fi - - -export BUILD_REVISION=jenkins - -# Unlock -if ! test -f ~/Library/Keychains/"$KEYCHAIN".keychain-db; then - echo "The '$KEYCHAIN' keychain is not available." - exit 1 -fi -security default-keychain -s "$KEYCHAIN.keychain" -security list-keychains -s "$KEYCHAIN.keychain" -echo "Unlock keychain" -security unlock-keychain -p "$(cat "$KEYCHAIN_PWD_FILE")" -echo "Increase keychain unlock timeout to 6 hours" -security set-keychain-settings -lut 21600 -security -v find-identity "$KEYCHAIN.keychain" - -# Prevent dialogs from asking for permissions. -# http://stackoverflow.com/a/40039594/183422 -# Discard output since there can be a *lot* of it. -security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$(cat "$KEYCHAIN_PWD_FILE")" "$KEYCHAIN.keychain" >/dev/null 2>&1 - -# clean mono keypairs (used in tests) -rm -rf ~/.config/.mono/keypairs/ - -# Run tests -RC=0 -make -C tests "$TARGET" || RC=$? - -# upload of the final html report -if test -n "$PUBLISH"; then - ./jenkins/publish-results.sh -fi - -if [[ x$RC != x0 ]]; then - report_error - exit $RC -fi - -printf "✅ [Test run succeeded](%s)\\n" "$URL" >> "$WORKSPACE/jenkins/pr-comments.md" - -if test -f "$WORKSPACE/jenkins/failure-stamp"; then - echo "Something went wrong:" - cat "$WORKSPACE/jenkins/pr-comments.md" - exit 1 -fi diff --git a/jenkins/utils.groovy b/jenkins/utils.groovy deleted file mode 100644 index 7fbee4d951..0000000000 --- a/jenkins/utils.groovy +++ /dev/null @@ -1,12 +0,0 @@ -def reportGitHubStatus(commitHash, context, backref, statusResult, statusResultMessage) { - step([ - $class: 'GitHubCommitStatusSetter', - reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/xamarin/xamarin-macios"], - commitShaSource: [$class: "ManuallyEnteredShaSource", sha: commitHash], - contextSource: [$class: 'ManuallyEnteredCommitContextSource', context: context], - statusBackrefSource: [$class: 'ManuallyEnteredBackrefSource', backref: backref], - statusResultSource: [$class: 'ConditionalStatusResultSource', results: [[$class: 'AnyBuildResult', state: statusResult, message: statusResultMessage]]] - ]) -} - -return this diff --git a/jenkins/vsts-device-tests-set-status.sh b/jenkins/vsts-device-tests-set-status.sh deleted file mode 100755 index afb69830fe..0000000000 --- a/jenkins/vsts-device-tests-set-status.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash -eux - -cd "$(dirname "${BASH_SOURCE[0]}")/.." - -TOKEN= -START= -DEVICE_TYPE= -while ! test -z "${1:-}"; do - case "$1" in - --token=*) - TOKEN="${1:8}" - shift - ;; - --token) - TOKEN="$2" - shift 2 - ;; - --start) - START=1 - shift - ;; - --device=*) - DEVICE_TYPE="${1:9}" - shift - ;; - --device) - DEVICE_TYPE="$2" - shift 2 - ;; - *) - echo "Unknown argument: $1" - exit 1 - ;; - esac -done - -if test -z "$TOKEN"; then - echo "The GitHub token is required (--token=)" - exit 1 -fi - -if test -z "$DEVICE_TYPE"; then - # set a default value - DEVICE_TYPE="iOS/tvOS" -fi - -VSTS_BUILD_URL="${SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${SYSTEM_TEAMPROJECT}/_build/index?buildId=${BUILD_BUILDID}&view=ms.vss-test-web.test-result-details" - -# Add a GitHub status to the commit we're testing -GH_STATE=failure -DESCRIPTION="Running device tests" -RESULT_EMOJII= -if test -n "$START"; then - GH_STATE=pending - DESCRIPTION="Running device tests on $DEVICE_TYPE" -else - case "$(echo "$AGENT_JOBSTATUS" | tr '[:upper:]' '[:lower:]')" in - succeeded) - GH_STATE=success - DESCRIPTION="Device tests passed on $DEVICE_TYPE" - RESULT_EMOJII="✅ " - ;; - failed | canceled | succeededwithissues | *) - GH_STATE=error - DESCRIPTION="Device tests completed ($AGENT_JOBSTATUS) on $DEVICE_TYPE" - RESULT_EMOJII="đŸ”Ĩ " - ;; - esac -fi -./jenkins/add-commit-status.sh --token="$TOKEN" --hash="$BUILD_REVISION" --state="$GH_STATE" --target-url="$VSTS_BUILD_URL" --description="$DESCRIPTION" --context="VSTS: device tests ($DEVICE_TYPE)" - -if test -z "$START"; then - # When we're done, add a GitHub comment to the commit we're testing - MESSAGE_FILE=commit-message.txt - cleanup () - { - rm -f "$MESSAGE_FILE" - } - trap cleanup ERR - trap cleanup EXIT - - HTML_REPORT="" - if [[ $DEVICE_TYPE == *"DDFun"* ]]; then - printf "### :construction: Experimental DDFun pipeline\\n" > "$MESSAGE_FILE" - else - P=$(cat tmp.p) - HTML_REPORT=": [Html Report](http://xamarin-storage/${P}/jenkins-results/tests/index.html)" - fi - - printf "%s%s on [Azure DevOps](%s)($DEVICE_TYPE)%s %s\\n\\n" "$RESULT_EMOJII" "$DESCRIPTION" "$VSTS_BUILD_URL" "$HTML_REPORT" "$RESULT_EMOJII" >> "$MESSAGE_FILE" - - FILE=$PWD/tests/TestSummary.md - if ! test -f "$FILE"; then - printf "đŸ”Ĩ Tests failed catastrophically on $DEVICE_TYPE (no summary found)\\n" >> "$MESSAGE_FILE" - else - cat "$FILE" >> "$MESSAGE_FILE" - fi - - ./jenkins/add-commit-comment.sh --token="$TOKEN" --file="$MESSAGE_FILE" "--hash=$BUILD_REVISION" -fi diff --git a/tests/common/Configuration.cs b/tests/common/Configuration.cs index 52bb9117b9..a4e0615165 100644 --- a/tests/common/Configuration.cs +++ b/tests/common/Configuration.cs @@ -221,7 +221,7 @@ namespace Xamarin.Tests { public static string EvaluateVariable (string variable) { var output = new StringBuilder (); - var rv = ExecutionHelper.Execute ("/usr/bin/make", new string [] { "-C", Path.Combine (SourceRoot, "jenkins"), "print-abspath-variable", $"VARIABLE={variable}" }, environmentVariables: null, stdout: output, stderr: output, timeout: TimeSpan.FromSeconds (5)); + var rv = ExecutionHelper.Execute ("/usr/bin/make", new string [] { "-C", Path.Combine (SourceRoot, "tools", "devops"), "print-abspath-variable", $"VARIABLE={variable}" }, environmentVariables: null, stdout: output, stderr: output, timeout: TimeSpan.FromSeconds (5)); if (rv != 0) throw new Exception ($"Failed to evaluate variable '{variable}'. Exit code: {rv}. Output:\n{output}"); var result = output.ToString ().Split (new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Where (v => v.StartsWith (variable + "=", StringComparison.Ordinal)).SingleOrDefault ();