From db34a5b0ca05f3a2d36d39d0bbded5e3499fe6f8 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 9 May 2018 12:25:10 +0200 Subject: [PATCH 1/8] Add support for building on Jenkins. --- Make.config | 1 + Makefile | 10 +- jenkins/Jenkinsfile | 477 +++++++++++++++++++++++++++++++++++++ jenkins/build-api-diff.sh | 9 +- jenkins/build-package.sh | 7 + jenkins/build.sh | 18 +- jenkins/compare.sh | 31 ++- jenkins/productsign.sh | 59 +++++ jenkins/publish-results.sh | 38 +++ jenkins/run-tests.sh | 67 +++++- jenkins/utils.groovy | 11 + 11 files changed, 702 insertions(+), 26 deletions(-) create mode 100644 jenkins/Jenkinsfile create mode 100755 jenkins/build-package.sh create mode 100755 jenkins/productsign.sh create mode 100755 jenkins/publish-results.sh create mode 100644 jenkins/utils.groovy diff --git a/Make.config b/Make.config index 40cba73dff56..3c7a1301469f 100644 --- a/Make.config +++ b/Make.config @@ -84,6 +84,7 @@ MIN_OSX_VERSION_FOR_IOS=10.11 MIN_OSX_VERSION_FOR_MAC=10.11 IOS_SDK_VERSION=11.4 +# When bumping OSX_SDK_VERSION also update the macOS version where we execute on bots in jenkins/Jenkinsfile (in the 'node' element) OSX_SDK_VERSION=10.13 WATCH_SDK_VERSION=4.3 TVOS_SDK_VERSION=11.4 diff --git a/Makefile b/Makefile index 9ffadfbdd048..7748749b8472 100644 --- a/Makefile +++ b/Makefile @@ -179,13 +179,11 @@ endif package: mkdir -p ../package - $(MAKE) -C ../maccore package + $(MAKE) -C $(MACCORE_PATH) package # copy .pkg, .zip and *updateinfo to the packages directory to be uploaded to storage - cp ../maccore/release/*.pkg ../package - -cp ../maccore/release/*.zip ../package - -cp ../maccore/release/*updateinfo ../package - -cp ../maccore/tests/*.zip ../package - -cp ../xamarin-macios/tests/*.zip ../package + cp $(MACCORE_PATH)/release/*.pkg ../package + cp $(MACCORE_PATH)/release/*.zip ../package + cp $(MACCORE_PATH)/release/*updateinfo ../package install-system: install-system-ios install-system-mac @# Clean up some old files diff --git a/jenkins/Jenkinsfile b/jenkins/Jenkinsfile new file mode 100644 index 000000000000..21a6d173ca6c --- /dev/null +++ b/jenkins/Jenkinsfile @@ -0,0 +1,477 @@ +#!/bin/groovy + +// global variables +repository = "xamarin/xamarin-macios" +isPr = false +branchName = null +gitHash = null +packagePrefix = null +virtualPath = null +xiPackageUrl = null +xmPackageUrl = null +utils = null +errorMessage = null +currentStage = null + +xiPackageFilename = null +xmPackageFilename = null +manifestFilename = null +reportPrefix = null +createFinalStatus = true +skipLocalTestRunReason = "" + +def abortExecutingBuilds () +{ + // This runs into problems with the Jenkins sandbox: + // org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method jenkins.model.Jenkins getItemByFullName java.lang.String + // so disable for now. + + // def job = Jenkins.instance.getItemByFullName (env.JOB_NAME) + // for (build in job.builds) { + // if (!build.isBuilding ()) + // continue + + // 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}") + // } + // } + // } +} + +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 +} + +def githubAddComment (url, markdown) +{ + 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 reportFinalStatus (err, gitHash, currentStage) +{ + if (!createFinalStatus) + return + + def commentFile = "${workspace}/xamarin-macios/jenkins/pr-comments.md" + def comment = null + def status = currentBuild.currentResult + + if ("${status}" == "SUCCESS" && err == "") { + comment = "✅ [Jenkins job](${env.RUN_DISPLAY_URL}) succeeded" + } else { + comment = "đŸ”Ĩ [Jenkins job](${env.RUN_DISPLAY_URL}) failed in stage '${currentStage}' đŸ”Ĩ" + if (err != "") + comment += " : ${err}" + manager.addErrorBadge (comment) + manager.buildFailure () + } + + if (fileExists (commentFile)) + comment += "\n\n" + readFile ("${commentFile}") + + addComment ("${comment}") +} + +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, virtualPath) +{ + step ([ + $class: 'WAStoragePublisher', + allowAnonymousAccess: true, + cleanUpContainer: false, + cntPubAccess: true, + containerName: "wrench", + doNotFailIfArchivingReturnsNothing: false, + doNotUploadIndividualFiles: false, + doNotWaitForPreviousBuild: true, + excludeFilesPath: '', + filesPath: glob, + storageAccName: 'bosstoragemirror', + storageCredentialId: 'bc6a99d18d7d9ca3f6bf6b19e364d564', + uploadArtifactsOnlyIfSuccessful: false, + uploadZips: false, + virtualPath: virtualPath + ]) +} + +def runXamarinMacTests (url, macOS) +{ + try { + echo ("Executing on ${env.NODE_NAME}") + echo ("URL: ${url}") + sh ("env") + sh ("rm -f *.zip") + sh ("curl -L '${url}' --output mac-test-package.zip") + sh ("rm -rf mac-test-package") + sh ("unzip -o mac-test-package.zip") + sh ("cd mac-test-package && ./system-dependencies.sh --provision-mono --ignore-autotools --ignore-xamarin-studio --ignore-xcode --ignore-osx --ignore-cmake") + sh ("make -C mac-test-package/tests exec-mac-dontlink") + sh ("make -C mac-test-package/tests exec-mac-apitest") + } finally { + sh ("rm -rf mac-test-package *.zip") + } +} + +timestamps { + node ('xamarin-macios && macos-10.13') { + try { + timeout (time: 9, unit: 'HOURS') { + // This runs into problems with the Jenkins sandbox: + // stage ("Checking for previous builds") { + // abortExecutingBuilds () + // } + + // 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" + withEnv ([ + "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}") + scmVars = checkout scm + isPr = (env.CHANGE_ID && !env.CHANGE_ID.empty ? true : false) + branchName = env.BRANCH_NAME + 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) { + if (!githubGetPullRequestLabels ().contains ("build-package")) { + // 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 the label 'build-package'.") + return + } + + skipLocalTestRunReason = "Not running tests here because they're run on public Jenkins." + } + + dir ("${workspace}") { + stage ('Provisioning') { + currentStage = "${STAGE_NAME}" + echo ("Building on ${env.NODE_NAME}") + sh ("${workspace}/xamarin-macios/jenkins/provision-deps.sh") + } + + stage ('Build') { + currentStage = "${STAGE_NAME}" + echo ("Building on ${env.NODE_NAME}") + sh ("${workspace}/xamarin-macios/jenkins/build.sh --configure-flags --enable-xamarin") + } + + stage ('Packaging') { + currentStage = "${STAGE_NAME}" + echo ("Building on ${env.NODE_NAME}") + sh ("${workspace}/xamarin-macios/jenkins/build-package.sh") + sh (script: "ls -la ${workspace}/package", returnStatus: true /* don't throw exceptions if something goes wrong */) + } + + stage ('Signing') { + currentStage = "${STAGE_NAME}" + echo ("Building on ${env.NODE_NAME}") + 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}") + } + withCredentials ([string (credentialsId: 'codesign_keychain_pw', variable: 'PRODUCTSIGN_KEYCHAIN_PASSWORD')]) { + sh ("${workspace}/xamarin-macios/jenkins/productsign.sh") + } + } + + stage ('Upload to Azure') { + currentStage = "${STAGE_NAME}" + virtualPath = "jenkins/${branchName}/${gitHash}/${env.BUILD_NUMBER}" + packagePrefix = "https://bosstoragemirror.blob.core.windows.net/wrench/${virtualPath}/package" + + // Create metadata.json and manifest + def uploadingFiles = findFiles (glob: "package/*") + def manifest = "" + def metadata = "[\n" + for (int i = 0; i < uploadingFiles.length; i++) { + def file = uploadingFiles [i] + def f_length = file.length; + def md5 = sh (returnStdout: true, script: "md5 -q '${file}'").trim () + manifest += "${packagePrefix}/${file.name}\n" + metadata += " {\n \"file\": \"${file.name}\",\n \"md5\": \"${md5}\",\n \"size\": ${f_length}\n }" + if (i < uploadingFiles.length - 1) + metadata += "," + metadata +="\n" + } + metadata += "]\n" + manifest += "${packagePrefix}/metadata.json\n" + manifest += "${packagePrefix}/manifest\n" + writeFile (file: "package/manifest", text: manifest) + writeFile (file: "package/metadata.json", text: metadata) + + sh ("ls -la package") + uploadFiles ("package/*", 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", "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", "jenkins/${branchName}/latest") + + manifestFilename = "manifest" + } + + stage ('Publish builds to GitHub') { + currentStage = "${STAGE_NAME}" + utils = load ("${workspace}/xamarin-macios/jenkins/utils.groovy") + if (xiPackageFilename != null) { + xiPackageUrl = "${packagePrefix}/${xiPackageFilename}" + utils.reportGitHubStatus (gitHash, 'jenkins-PKG-Xamarin.iOS', "${xiPackageUrl}", 'SUCCESS', "${xiPackageFilename}") + } + if (xmPackageFilename != null) { + xmPackageUrl = "${packagePrefix}/${xmPackageFilename}" + utils.reportGitHubStatus (gitHash, 'jenkins-PKG-Xamarin.Mac', "${xmPackageUrl}", 'SUCCESS', "${xmPackageFilename}") + } + if (manifestFilename != null) { + def manifestUrl = "${packagePrefix}/${manifestFilename}" + utils.reportGitHubStatus (gitHash, '${manifestFilename}', "${manifestUrl}", 'SUCCESS', "${manifestFilename}") + } + } + + dir ('xamarin-macios') { + stage ('Launch external tests') { + currentStage = "${STAGE_NAME}" + if (isPr) { + echo "Currently not launching external tests 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')]) { + 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=jenkins/${branchName} BUILD_WORK_HOST=${env.NODE_NAME} 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}'") + } + } + } + + stage ('Install Provisioning Profiles') { + currentStage = "${STAGE_NAME}" + sh ("${workspace}/maccore/tools/install-qa-provisioning-profiles.sh") + } + + stage ('Publish reports') { + currentStage = "${STAGE_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}" + 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}" + 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") + } + + stage ("Package XM tests") { + currentStage = "${STAGE_NAME}" + sh ("make -C ${workspace}/xamarin-macios/tests package-tests") + uploadFiles ("tests/*.zip", virtualPath) + } + + timeout (time: 6, 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 + def url = "https://bosstoragemirror.blob.core.windows.net/wrench/${virtualPath}/tests/mac-test-package.zip" + def firstOS = sh (returnStdout: true, script: "grep ^MIN_OSX_SDK_VERSION= '${workspace}/xamarin-macios/Make.config' | sed 's/.*=//'").trim ().split ("\\.")[1].toInteger () + def lastOS = sh (returnStdout: true, script: "grep ^OSX_SDK_VERSION= '${workspace}/xamarin-macios/Make.config' | sed 's/.*=//'").trim ().split ("\\.")[1].toInteger () + for (os = firstOS; os < lastOS; os++) { + def macOS = "${os}" // Need to bind the label variable before the closure + builders ["XM tests on 10.${macOS}"] = { + try { + node ("xamarin-macios && macos-10.${macOS}") { + stage ("Running XM tests on '10.${macOS}'") { + runXamarinMacTests (url, "macOS 10.${macOS}") + } + } + } catch (err) { + currentStage = "Running XM tests on '10.${macOS}'" + 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) + } else { + echo ("Html report: ${reportPrefix}/tests/index.html") + sh ("${workspace}/xamarin-macios/jenkins/run-tests.sh --target=wrench-jenkins --publish --keychain=xamarin-macios") + } + } + stage ('Test docs') { + currentStage = "${STAGE_NAME}" + echo ("Building on ${env.NODE_NAME}") + sh ("make -C ${workspace}/xamarin-macios/tests wrench-docs") + } + } + + // Run it all parallelized + parallel builders + } + } + } // dir ("xamarin-macios") + } // dir ("${workspace}") + } + reportFinalStatus ("", "${gitHash}", "${currentStage}") + } // timeout + } catch (err) { + reportFinalStatus ("${err}", "${gitHash}", "${currentStage}") + } finally { + 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 */) + } + } + } // node +} // timestamps diff --git a/jenkins/build-api-diff.sh b/jenkins/build-api-diff.sh index 7e73b98b227b..cfdbabb53f14 100755 --- a/jenkins/build-api-diff.sh +++ b/jenkins/build-api-diff.sh @@ -12,4 +12,11 @@ trap report_error ERR export BUILD_REVISION=jenkins make -j8 -C tools/apidiff jenkins-api-diff -printf "✅ [API Diff (from stable)](%s/API_20diff_20_28from_20stable_29)\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" +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-package.sh b/jenkins/build-package.sh new file mode 100755 index 000000000000..150b8686a799 --- /dev/null +++ b/jenkins/build-package.sh @@ -0,0 +1,7 @@ +#!/bin/bash -ex + +cd "$(dirname "${BASH_SOURCE[0]}")/.." +#WORKSPACE=$(pwd) + +rm -Rf ../package +make package diff --git a/jenkins/build.sh b/jenkins/build.sh index 9872e0e17fa0..cdbe6c0879fa 100755 --- a/jenkins/build.sh +++ b/jenkins/build.sh @@ -9,6 +9,10 @@ report_error () } trap report_error ERR +if [[ x$1 == x--configure-flags ]]; then + CONFIGURE_FLAGS="$2" +fi + ls -la "$WORKSPACE/jenkins" echo "$WORKSPACE/jenkins/pr-comments.md:" cat "$WORKSPACE/jenkins/pr-comments.md" @@ -20,7 +24,8 @@ 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 won't check if we're doing a device build." + echo "Could not find the environment variable ghprbPullId, so forcing a device build." + ENABLE_DEVICE_BUILD=1 else 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 @@ -47,11 +52,16 @@ else fi if test -n "$ENABLE_DEVICE_BUILD"; then - ./configure + ./configure "$CONFIGURE_FLAGS" else - ./configure --disable-ios-device + ./configure "$CONFIGURE_FLAGS" --disable-ios-device fi -time make world +make reset +make git-clean-all +make print-versions + +time make -j8 +time make install -j8 printf "✅ [Build succeeded](%s/console)\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" diff --git a/jenkins/compare.sh b/jenkins/compare.sh index afd98cc8e19e..491ce314200c 100755 --- a/jenkins/compare.sh +++ b/jenkins/compare.sh @@ -11,15 +11,21 @@ report_error () } trap report_error ERR +# SC2154: ghprbPullId is referenced but not assigned. +# shellcheck disable=SC2154 +if test -n "$ghprbPullId"; then + if ./jenkins/fetch-pr-labels.sh --check=skip-api-comparison; then + printf "❎ Skipped API comparison because the PR has the label 'skip-api-comparison'\\n" >> "$WORKSPACE/jenkins/pr-comments.md" + exit 0 + fi +fi -if ./jenkins/fetch-pr-labels.sh --check=skip-api-comparison; then - printf "❎ Skipped API comparison because the PR has the label 'skip-api-comparison'\\n" >> "$WORKSPACE/jenkins/pr-comments.md" - exit 0 +if test -z "$ghprbPullId"; then + BASE=HEAD +else + BASE="origin/pr/$ghprbPullId/merge" fi -# SC2154: ghprbPullId is referenced but not assigned. -# shellcheck disable=SC2154 -BASE="origin/pr/$ghprbPullId/merge" if ! git rev-parse "$BASE" >/dev/null 2>&1; then echo "Can't compare API and create generator diff because the pull request has conflicts that must be resolved first (the branch '$BASE' doesn't exist)." printf "đŸ”Ĩ [Failed to compare API and create generator diff because the pull request has conflicts that must be resolved first](%s/console) đŸ”Ĩ\\n" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" @@ -34,7 +40,16 @@ cp -R tools/comparison/apidiff/diff jenkins-results/apicomparison/ cp tools/comparison/apidiff/*.html jenkins-results/apicomparison/ cp -R tools/comparison/generator-diff jenkins-results/generator-diff -printf "✅ [API Diff (from PR only)](%s/API_20diff_20_28PR_20only_29)" "$BUILD_URL" >> "$WORKSPACE/jenkins/pr-comments.md" +if [[ "x$1" == "x--publish" ]]; then + URL_PREFIX=$(./jenkins/publish-results.sh | grep "^Url Prefix: " | sed 's/^Url Prefix: //') + URL_API="$URL_PREFIX/apicomparison/index.html" + URL_GENERATOR="$URL_PREFIX/generator-diff/index.html" +else + URL_API="$BUILD_URL/API_20diff_20_28PR_20only_29" + URL_GENERATOR="$BUILD_URL/Generator_20Diff" +fi + +printf "✅ [API Diff (from PR only)](%s)" "$URL_API" >> "$WORKSPACE/jenkins/pr-comments.md" if ! grep "href=" jenkins-results/apicomparison/api-diff.html >/dev/null 2>&1; then printf " (no change)" >> "$WORKSPACE/jenkins/pr-comments.md" elif perl -0777 -pe 's/