@@ -94,28 +94,71 @@ for check_run_id in $(jq -r .check_runs[].id api/check_suite_runs); do
9494
9595 gh api " repos/${GITHUB_REPOSITORY} /check-runs/${check_run_id} " > api/check_run
9696 job_url=" $( jq -r .details_url api/check_run) "
97+ job_name=" $( jq -r .name api/check_run) "
9798
98- # Figure out where the JUnit XML report lives and the Trunk variant based on the job name. If new
99- # jobs are added or renamed, you will need to change this too.
99+ # We need to somehow download the JUnit XML from the job artifacts, and there are no good
100+ # solutions available in Buildomat to do so:
100101 #
101- # The Trunk variant allows to differentiate flaky tests by platform, and should be the OS name.
102- job_name=" $( jq -r .name api/check_run) "
103- case " ${github_app} / ${job_name} " in
104- " buildomat / build-and-test (helios)" )
105- artifact_series=" junit-helios"
106- artifact_name=" junit.xml"
107- variant=" helios"
108- ;;
109- " buildomat / build-and-test (ubuntu-22.04)" )
110- artifact_series=" junit-linux"
111- artifact_name=" junit.xml"
112- variant=" ubuntu"
113- ;;
114- * )
115- echo " unsupported job name, skipping upload: ${job_name} "
116- continue
117- ;;
118- esac
102+ # - Buildomat supports publishing artifacts at pre-defined URLs with its [[publish]] config
103+ # block, and that's what this script originally used. The problem is, if jobs run multiple
104+ # times for the same commit (for example in case of a retry) Buildomat will only publish the
105+ # artifact of the first job, not for any followup jobs.
106+ #
107+ # - Buildomat has a JSON API that does expose the job outputs, but it's behind authentication
108+ # and this workflow cannot access it. It would also require everyone tweaking the script to
109+ # obtain credentials before running the script locally.
110+ #
111+ # - Buildomat provides an unauthenticated HTML page with all the job details, including download
112+ # links for the job outpouts. It requires scraping the HTML to figure out the correct link.
113+ #
114+ # Out of the three options, the second would be ideal, but cannot implemented now. The first
115+ # option was implemented previously, but to detect flaky tests Trunk needs the correct JUnit
116+ # files when a job is retried. This only leaves us with the third option, which while not ideal
117+ # seems to work fine for now. Sorry.
118+ log_step " detecting the presence of a JUnit report in job ${job_name} "
119+ found_link=" "
120+ # curl flags:
121+ # -f: exit 1 if the response is a 4xx or a 5xx
122+ # -L: follow redirects
123+ #
124+ # grep flags:
125+ # -h: don't output file names
126+ # -o: only print what matches, not the whole line
127+ # -P: use perl regexes (needed for \K)
128+ #
129+ # Regex details:
130+ # - We first match `href="`, to only get links as part of an <a> tag.
131+ # - The \K then instructs grep to only print matching text *after* the \K.
132+ # - We finally include everything that looks like a link until a `"` is found.
133+ for link in $( curl -fL --retry 3 " ${job_url} " | grep -hoP ' href="\Khttps://[^"]+' ) ; do
134+ case " ${link} " in
135+ # Look for Buildomat links for an artefact called "junit.xml".
136+ https://buildomat.eng.oxide.computer/wg/0/artefact/* /junit.xml)
137+ if [[ " ${found_link} " == " ${link} " ]]; then
138+ echo " note: found the same JUnit link multiple times, only using the first" >&2
139+ elif [[ " ${found_link} " == " " ]]; then
140+ echo " success: found ${link} " >&2
141+ rm -f git/junit.xml
142+ curl -fL -o git/junit.xml --retry 3 " ${link} "
143+ found_link=" ${link} "
144+ else
145+ # It could be possible to support multiple JUnit files, but we don't need that
146+ # so far. If you encounter this error feel free to add support for it.
147+ echo " error: found more than one JUnit reports:" >&2
148+ echo " - ${found_link} " >&2
149+ echo " - ${link} " >&2
150+ exit 1
151+ fi
152+ ;;
153+ * )
154+ echo " note: ignoring non-JUnit URL ${link} " >&2
155+ ;;
156+ esac
157+ done
158+ if [[ " ${found_link} " == " " ]]; then
159+ echo " skipping job ${job_name} , as it doesn't contain any JUnit report"
160+ continue
161+ fi
119162
120163 # Configure the environment to override Trunk's CI detection (with CUSTOM=true) and to provide all
121164 # the relevant information about the CI run. Otherwise Trunk will either pick up nothing (when
@@ -133,25 +176,24 @@ for check_run_id in $(jq -r .check_runs[].id api/check_suite_runs); do
133176 vars+=(" PR_TITLE=${pr_title} " )
134177 fi
135178
179+ echo >&2
136180 echo " these environmnent variables will be set:" >&2
137181 for var in " ${vars[@]} " ; do
138182 echo " ${var} " >&2
139183 done
140184
141- # The URL is configured through a [[publish]] block in the Buildomat job configuration.
142- log_step " downloading the JUnit XML report for check run ${check_run_id} ..."
143- junit_url=" https://buildomat.eng.oxide.computer/public/file/${GITHUB_REPOSITORY} /${artifact_series} /${commit} /${artifact_name} "
144- rm -f git/junit.xml
145- curl -fL -o git/junit.xml --retry 3 " ${junit_url} "
146-
147185 # Uploading to Trunk has to happen inside of the git repository at the current commit.
148- log_step " uploading the JUnit XML report of check run ${check_run_id} to Trunk..."
149- cd git/
150- env " ${vars[@]} " \
151- ../trunk flakytests upload \
152- --junit-paths junit.xml \
153- --variant " ${variant} " \
154- --org-url-slug " ${TRUNK_ORG_SLUG} " \
155- --token " ${TRUNK_TOKEN} "
156- cd ..
186+ if [[ -z " ${DRY_RUN+x} " ]]; then
187+ log_step " uploading the JUnit XML report of check run ${check_run_id} to Trunk..."
188+ cd git/
189+ env " ${vars[@]} " \
190+ ../trunk flakytests upload \
191+ --junit-paths junit.xml \
192+ --variant " ${variant} " \
193+ --org-url-slug " ${TRUNK_ORG_SLUG} " \
194+ --token " ${TRUNK_TOKEN} "
195+ cd ..
196+ else
197+ log_step " skipped upload to Trunk, we are in a dry run"
198+ fi
157199done
0 commit comments