Skip to content

Commit 36c0afd

Browse files
josephperrottannieyw
authored andcommitted
ci: rebase PRs before running CI checks (#20985)
PRs should be rebased before running and CI checks to test the code that would be merged, rather than the code of the repository the PR was created from at the time it was created. (cherry picked from commit 154757c)
1 parent 38a55b5 commit 36c0afd

File tree

4 files changed

+372
-28
lines changed

4 files changed

+372
-28
lines changed

.circleci/config.yml

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,6 @@ var_5: &job_defaults
2626
docker:
2727
- image: *docker_image
2828

29-
# Job step for checking out the source code from GitHub. This also ensures that the source code
30-
# is rebased on top of master.
31-
var_6: &checkout_code
32-
checkout:
33-
# After checkout, rebase on top of master. By default, PRs are not rebased on top of master,
34-
# which we want. See https://discuss.circleci.com/t/1662
35-
post: git pull --ff-only origin "refs/pull/${CI_PULL_REQUEST//*pull\//}/merge"
36-
3729
# Restores the cache that could be available for the current Yarn lock file. The cache usually
3830
# includes the node modules and the Bazel repository cache.
3931
var_7: &restore_cache
@@ -159,12 +151,34 @@ orbs:
159151
# push conflicts.
160152
queue: eddiewebb/[email protected]
161153

154+
155+
commands:
156+
checkout_and_rebase:
157+
description: Checkout and rebase the repository
158+
steps:
159+
- checkout
160+
- run:
161+
name: Set up environment
162+
environment:
163+
CIRCLE_GIT_BASE_REVISION: << pipeline.git.base_revision >>
164+
CIRCLE_GIT_REVISION: << pipeline.git.revision >>
165+
command: ./.circleci/env.sh
166+
- run:
167+
name: Rebase PR on target branch
168+
# After checkout, rebase on top of target branch.
169+
command: |
170+
if [ -n "$CIRCLE_PR_NUMBER" ]; then
171+
# User is required for rebase.
172+
git config user.name "angular-ci"
173+
git config user.email "angular-ci"
174+
node .circleci/rebase-pr.js
175+
fi
176+
162177
# -----------------------------------------------------------------------------------------
163178
# Job definitions. Jobs which are defined just here, will not run automatically. Each job
164179
# must be part of a workflow definition in order to run for PRs and push builds.
165180
# -----------------------------------------------------------------------------------------
166181
jobs:
167-
168182
# -----------------------------------
169183
# Job to test that everything builds with Bazel
170184
# -----------------------------------
@@ -174,7 +188,7 @@ jobs:
174188
environment:
175189
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
176190
steps:
177-
- *checkout_code
191+
- checkout_and_rebase
178192
- *restore_cache
179193
- *setup_bazel_ci_config
180194
- *setup_bazel_remote_execution
@@ -196,7 +210,7 @@ jobs:
196210
environment:
197211
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
198212
steps:
199-
- *checkout_code
213+
- checkout_and_rebase
200214
- *restore_cache
201215
- *setup_bazel_ci_config
202216
- *setup_bazel_remote_execution
@@ -218,7 +232,7 @@ jobs:
218232
environment:
219233
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
220234
steps:
221-
- *checkout_code
235+
- checkout_and_rebase
222236
- *restore_cache
223237
- *setup_bazel_ci_config
224238
- *setup_bazel_remote_execution
@@ -237,7 +251,7 @@ jobs:
237251
environment:
238252
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
239253
steps:
240-
- *checkout_code
254+
- checkout_and_rebase
241255
- *restore_cache
242256
- *setup_bazel_ci_config
243257
- *setup_bazel_remote_execution
@@ -260,7 +274,7 @@ jobs:
260274
environment:
261275
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
262276
steps:
263-
- *checkout_code
277+
- checkout_and_rebase
264278
- *restore_cache
265279
- *setup_bazel_ci_config
266280
- *setup_bazel_remote_execution
@@ -281,7 +295,7 @@ jobs:
281295
BROWSER_STACK_USERNAME: "angularteam1"
282296
BROWSER_STACK_ACCESS_KEY: "CaXMeMHD9pr5PHg8N7Jq"
283297
steps:
284-
- *checkout_code
298+
- checkout_and_rebase
285299
- *restore_cache
286300
- *setup_bazel_ci_config
287301
- *yarn_install
@@ -303,7 +317,7 @@ jobs:
303317
# a rate limit exception.
304318
KARMA_PARALLEL_BROWSERS: 2
305319
steps:
306-
- *checkout_code
320+
- checkout_and_rebase
307321
- *restore_cache
308322
- *setup_bazel_ci_config
309323
- *yarn_install
@@ -316,8 +330,11 @@ jobs:
316330
# ----------------------------------
317331
lint:
318332
<<: *job_defaults
333+
environment:
334+
CI_GIT_BASE_REVISION: << pipeline.git.base_revision >>
335+
CI_GIT_REVISION: << pipeline.git.revision >>
319336
steps:
320-
- *checkout_code
337+
- checkout_and_rebase
321338
- *restore_cache
322339
- *setup_bazel_ci_config
323340
- *yarn_install
@@ -342,7 +359,7 @@ jobs:
342359
# much about any failures that have made it into the main branch.
343360
command: |
344361
if [ -n "$CIRCLE_PR_NUMBER" ]; then
345-
yarn ng-dev commit-message validate-range --range << pipeline.git.base_revision >>...<<pipeline.git.revision>>
362+
yarn ng-dev commit-message validate-range --range $CI_COMMIT_RANGE
346363
fi
347364
- run: yarn ownerslint
348365
- run: yarn stylelint
@@ -362,7 +379,7 @@ jobs:
362379
environment:
363380
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
364381
steps:
365-
- *checkout_code
382+
- checkout_and_rebase
366383
- *restore_cache
367384
- *setup_bazel_ci_config
368385
- *setup_bazel_remote_execution
@@ -414,7 +431,7 @@ jobs:
414431
upload_release_packages:
415432
<<: *job_defaults
416433
steps:
417-
- *checkout_code
434+
- checkout_and_rebase
418435
- *restore_cache
419436
- *attach_release_output
420437
- *yarn_install
@@ -435,7 +452,7 @@ jobs:
435452
environment:
436453
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
437454
steps:
438-
- *checkout_code
455+
- checkout_and_rebase
439456
- *restore_cache
440457
- *attach_release_output
441458
- *setup_bazel_ci_config
@@ -473,7 +490,7 @@ jobs:
473490
<<: *job_defaults
474491
resource_class: xlarge
475492
steps:
476-
- *checkout_code
493+
- checkout_and_rebase
477494
- *restore_cache
478495
- *attach_release_output
479496
- *yarn_install
@@ -497,7 +514,7 @@ jobs:
497514
<<: *job_defaults
498515
resource_class: xlarge
499516
steps:
500-
- *checkout_code
517+
- checkout_and_rebase
501518
- *restore_cache
502519
- *attach_release_output
503520
- *setup_snapshot_builds
@@ -524,7 +541,7 @@ jobs:
524541
environment:
525542
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
526543
steps:
527-
- *checkout_code
544+
- checkout_and_rebase
528545
- *restore_cache
529546
- *setup_bazel_ci_config
530547
- *setup_bazel_remote_execution
@@ -545,7 +562,7 @@ jobs:
545562
environment:
546563
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
547564
steps:
548-
- *checkout_code
565+
- checkout_and_rebase
549566
- *restore_cache
550567
- *setup_bazel_ci_config
551568
- *setup_bazel_remote_execution
@@ -565,7 +582,7 @@ jobs:
565582
environment:
566583
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
567584
steps:
568-
- *checkout_code
585+
- checkout_and_rebase
569586
- *restore_cache
570587
- *setup_bazel_ci_config
571588
- *setup_bazel_remote_execution
@@ -586,7 +603,7 @@ jobs:
586603
environment:
587604
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
588605
steps:
589-
- *checkout_code
606+
- checkout_and_rebase
590607
- *restore_cache
591608
- *setup_bazel_ci_config
592609
- *setup_bazel_remote_execution
@@ -612,7 +629,7 @@ jobs:
612629
environment:
613630
GCP_DECRYPT_TOKEN: *gcp_decrypt_token
614631
steps:
615-
- *checkout_code
632+
- checkout_and_rebase
616633
- *restore_cache
617634
- *setup_bazel_binary
618635
- *setup_bazel_ci_config

.circleci/env-helpers.inc.sh

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
####################################################################################################
2+
# Helpers for defining environment variables for CircleCI.
3+
#
4+
# In CircleCI, each step runs in a new shell. The way to share ENV variables across steps is to
5+
# export them from `$BASH_ENV`, which is automatically sourced at the beginning of every step (for
6+
# the default `bash` shell).
7+
#
8+
# See also https://circleci.com/docs/2.0/env-vars/#using-bash_env-to-set-environment-variables.
9+
####################################################################################################
10+
11+
# Set and print an environment variable.
12+
#
13+
# Use this function for setting environment variables that are public, i.e. it is OK for them to be
14+
# visible to anyone through the CI logs.
15+
#
16+
# Usage: `setPublicVar <name> <value>`
17+
function setPublicVar() {
18+
setSecretVar $1 "$2";
19+
echo "$1=$2";
20+
}
21+
22+
# Set (without printing) an environment variable.
23+
#
24+
# Use this function for setting environment variables that are secret, i.e. should not be visible to
25+
# everyone through the CI logs.
26+
#
27+
# Usage: `setSecretVar <name> <value>`
28+
function setSecretVar() {
29+
# WARNING: Secrets (e.g. passwords, access tokens) should NOT be printed.
30+
# (Keep original shell options to restore at the end.)
31+
local -r originalShellOptions=$(set +o);
32+
set +x -eu -o pipefail;
33+
34+
echo "export $1=\"${2:-}\";" >> $BASH_ENV;
35+
36+
# Restore original shell options.
37+
eval "$originalShellOptions";
38+
}
39+
40+
41+
# Create a function to set an environment variable, when called.
42+
#
43+
# Use this function for creating setter for public environment variables that require expensive or
44+
# time-consuming computaions and may not be needed. When needed, you can call this function to set
45+
# the environment variable (which will be available through `$BASH_ENV` from that point onwards).
46+
#
47+
# Arguments:
48+
# - `<name>`: The name of the environment variable. The generated setter function will be
49+
# `setPublicVar_<name>`.
50+
# - `<code>`: The code to run to compute the value for the variable. Since this code should be
51+
# executed lazily, it must be properly escaped. For example:
52+
# ```sh
53+
# # DO NOT do this:
54+
# createPublicVarSetter MY_VAR "$(whoami)"; # `whoami` will be evaluated eagerly
55+
#
56+
# # DO this isntead:
57+
# createPublicVarSetter MY_VAR "\$(whoami)"; # `whoami` will NOT be evaluated eagerly
58+
# ```
59+
#
60+
# Usage: `createPublicVarSetter <name> <code>`
61+
#
62+
# Example:
63+
# ```sh
64+
# createPublicVarSetter MY_VAR 'echo "FOO"';
65+
# echo $MY_VAR; # Not defined
66+
#
67+
# setPublicVar_MY_VAR;
68+
# source $BASH_ENV;
69+
# echo $MY_VAR; # FOO
70+
# ```
71+
function createPublicVarSetter() {
72+
echo "setPublicVar_$1() { setPublicVar $1 \"$2\"; }" >> $BASH_ENV;
73+
}

.circleci/env.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/env bash
2+
3+
# Variables
4+
readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..")
5+
readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh";
6+
readonly bashEnvCachePath="$projectDir/.circleci/bash_env_cache";
7+
8+
# Load helpers and make them available everywhere (through `$BASH_ENV`).
9+
source $envHelpersPath;
10+
echo "source $envHelpersPath;" >> $BASH_ENV;
11+
12+
13+
####################################################################################################
14+
# Define PUBLIC environment variables for CircleCI.
15+
####################################################################################################
16+
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
17+
####################################################################################################
18+
setPublicVar CI "$CI"
19+
setPublicVar PROJECT_ROOT "$projectDir";
20+
# This is the branch being built; e.g. `pull/12345` for PR builds.
21+
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
22+
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
23+
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
24+
# `CI_COMMIT_RANGE` is only used on push builds (a.k.a. non-PR, non-scheduled builds and rerun
25+
# workflows of such builds).
26+
setPublicVar CI_GIT_BASE_REVISION "${CIRCLE_GIT_BASE_REVISION}";
27+
setPublicVar CI_GIT_REVISION "${CIRCLE_GIT_REVISION}";
28+
setPublicVar CI_COMMIT_RANGE "$CIRCLE_GIT_BASE_REVISION..$CIRCLE_GIT_REVISION";
29+
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
30+
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
31+
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
32+
setPublicVar CI_PR_REPONAME "$CIRCLE_PR_REPONAME";
33+
setPublicVar CI_PR_USERNAME "$CIRCLE_PR_USERNAME";
34+
35+
####################################################################################################
36+
# Decrypt GCP Credentials and store them as the Google default credentials.
37+
####################################################################################################
38+
mkdir -p "$HOME/.config/gcloud";
39+
openssl aes-256-cbc -d -in "${projectDir}/.circleci/gcp_token" \
40+
-md md5 -k "$CIRCLE_PROJECT_REPONAME" -out "$HOME/.config/gcloud/application_default_credentials.json"
41+
####################################################################################################
42+
# Set bazel configuration for CircleCI runs.
43+
####################################################################################################
44+
cp "${projectDir}/.circleci/bazel.linux.rc" "$HOME/.bazelrc";
45+
46+
####################################################################################################
47+
####################################################################################################
48+
## Source `$BASH_ENV` to make the variables available immediately. ##
49+
## ***NOTE: This must remain the the last action in this script*** ##
50+
####################################################################################################
51+
####################################################################################################
52+
source $BASH_ENV;

0 commit comments

Comments
 (0)