diff --git a/.github/workflows/root-ci-config/build_root.py b/.github/workflows/root-ci-config/build_root.py index 067c42c9213ab..7ae789e70baf6 100755 --- a/.github/workflows/root-ci-config/build_root.py +++ b/.github/workflows/root-ci-config/build_root.py @@ -163,6 +163,11 @@ def main(): head_ref_dst = head_ref_dst or "__tmp" rebase("src", "origin", base_head_sha, head_ref_dst, args.head_sha) + elif args.sha: + # Builds triggered by a push to a branch must build exactly the pushed + # commit: git_pull() picks up wherever the branch points to when this + # job starts, which may already be a later commit. + checkout_commit("src", args.repository, args.sha) testing: bool = options_dict['testing'] == "ON" @@ -332,6 +337,29 @@ def git_pull(directory: str, repository: str, branch: str): die(returncode, f"Failed to pull {branch}") +@github_log_group("Checkout pushed commit") +def checkout_commit(directory: str, repository: str, sha: str): + """Reset the checkout to exactly the commit that triggered the build. + + The commit normally arrives with the fetch of its branch in git_pull(); + if it is missing (e.g. the branch was force-pushed in the meantime), it + is fetched explicitly. + """ + targetdir = os.path.join(WORKDIR, directory) + returncode = subprocess_with_log(f""" + cd '{targetdir}' + git reset --hard {sha} + """) + if returncode != 0: + returncode = subprocess_with_log(f""" + cd '{targetdir}' + git fetch {repository} {sha} + git reset --hard {sha} + """) + if returncode != 0: + die(returncode, f"Failed to check out commit {sha}") + + @github_log_group("Download previous build artifacts") def download_artifacts(obj_prefix: str): try: diff --git a/.github/workflows/root-ci.yml b/.github/workflows/root-ci.yml index c3dbb65dfac62..0af636192a117 100644 --- a/.github/workflows/root-ci.yml +++ b/.github/workflows/root-ci.yml @@ -186,6 +186,9 @@ jobs: env: OVERRIDES: ${{ github.event_name == 'push' && format('{0} {1} {2}', '--overrides', env.GLOBAL_OVERRIDES, join( matrix.overrides, ' ')) || '' }} BASE_REF: ${{ github.event_name == 'push' && github.ref_name || inputs.ref_name }} + # For pushes, build exactly the pushed commit, not wherever the + # branch happens to be when the job starts (issue #14061). + SHA: ${{ github.event_name == 'push' && format('--sha {0}', github.sha) || '' }} run: | [ -d "${VIRTUAL_ENV_DIR}" ] && source ${VIRTUAL_ENV_DIR}/bin/activate echo "Python is now $(which python3) $(python3 --version)" @@ -196,6 +199,7 @@ jobs: --upload_artifacts false \ --binaries ${{ github.event_name == 'schedule' }} \ --base_ref ${BASE_REF} \ + ${SHA} \ --repository ${{ github.server_url }}/${{ github.repository }} \ ${OVERRIDES} @@ -344,6 +348,7 @@ jobs: --platform windows10 --incremental false --base_ref ${{ github.ref_name }} + --sha ${{ github.sha }} --binaries ${{ startsWith(github.ref, 'refs/tags/') }} --repository ${{ github.server_url }}/${{ github.repository }} --architecture ${{ matrix.target_arch }}" @@ -581,6 +586,7 @@ jobs: --platform_config ${{ matrix.platform_config }} --incremental false --base_ref ${{ github.ref_name }} + --sha ${{ github.sha }} --binaries ${{ startsWith(github.ref, 'refs/tags/') }} --repository ${{ github.server_url }}/${{ github.repository }} --overrides ${GLOBAL_OVERRIDES} ${OVERRIDES}