Skip to content

Commit 5713faa

Browse files
committed
build: autosquashes SHAs as part of merge-pr script (angular#21791)
To support `git checkin --fixup` and `git checkin —squash` we need to make sure that `merge-pr` squashes the sepecial commits before they are merged. For more details see: https://robots.thoughtbot.com/autosquashing-git-commits PR Close angular#21791
1 parent 23596b3 commit 5713faa

3 files changed

Lines changed: 76 additions & 50 deletions

File tree

scripts/github/merge-pr

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,32 @@ set -u -e -o pipefail
55
BASEDIR=$(dirname "$0")
66
BASEDIR=`(cd $BASEDIR; pwd)`
77

8-
if [ $# -eq 0 ]; then
8+
PR_NUMBER=0
9+
PUSH_UPSTREAM=1
10+
while [[ $# -gt 0 ]]
11+
do
12+
key="$1"
13+
14+
case $key in
15+
--dryrun)
16+
PUSH_UPSTREAM=0
17+
shift # past argument
18+
;;
19+
*) # unknown option
20+
PR_NUMBER="$1" # save it in an array for later
21+
shift # past argument
22+
;;
23+
esac
24+
done
25+
26+
if [ "$PR_NUMBER" -eq 0 ]; then
927
echo "Merge github PR into the target branches"
1028
echo
11-
echo "$0 PR_NUMBER"
29+
echo "$0 PR_NUMBER [--dryrun]"
1230
echo
1331
exit 0
1432
fi
1533

16-
PR_NUMBER="$1"
1734
CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD`
1835
PR_SHA_COUNT=`curl -s https://api.github.com/repos/angular/angular/pulls/$PR_NUMBER | node $BASEDIR/utils/json_extract.js commits`
1936
PR_LABELS=`curl -s https://api.github.com/repos/angular/angular/issues/$PR_NUMBER/labels`
@@ -51,63 +68,59 @@ fi
5168

5269

5370
CHECKOUT_MASTER="git checkout merge_pr_master"
54-
CHECKOUT_PATCH="git checkout merge_pr_$PATCH_BRANCH"
71+
CHECKOUT_PATCH="git checkout merge_pr_patch"
5572
RESTORE_BRANCH="git checkout $CURRENT_BRANCH"
56-
FETCH_PR="git fetch [email protected]:angular/angular.git pull/$PR_NUMBER/head:angular/pr/$PR_NUMBER heads/master:merge_pr_master heads/$PATCH_BRANCH:merge_pr_$PATCH_BRANCH -f"
57-
PUSH_BRANCHES="git push [email protected]:angular/angular.git merge_pr_master:master merge_pr_$PATCH_BRANCH:$PATCH_BRANCH"
58-
CHERRY_PICK_PR="git cherry-pick angular/pr/$PR_NUMBER~$PR_SHA_COUNT..angular/pr/$PR_NUMBER"
59-
REWRITE_MESSAGE="git filter-branch -f --msg-filter \"$BASEDIR/utils/github_closes.js $PR_NUMBER\" HEAD~$PR_SHA_COUNT..HEAD"
73+
FETCH_PR="git fetch [email protected]:angular/angular.git pull/$PR_NUMBER/head:merge_pr heads/master:merge_pr_master heads/$PATCH_BRANCH:merge_pr_patch -f"
74+
BASE_PR="git checkout merge_pr~$PR_SHA_COUNT -B merge_pr_base"
75+
PUSH_BRANCHES="git push [email protected]:angular/angular.git merge_pr_master:master merge_pr_patch:$PATCH_BRANCH"
76+
SQUASH_PR="git rebase --autosquash --interactive merge_pr_base merge_pr"
77+
CHERRY_PICK_PR="git cherry-pick merge_pr_base..merge_pr"
78+
REWRITE_MESSAGE="git filter-branch -f --msg-filter \"$BASEDIR/utils/github_closes.js $PR_NUMBER\" merge_pr_base..merge_pr"
6079

6180
echo "======================"
6281
echo "GitHub Merge PR Steps"
6382
echo "======================"
6483
echo " $FETCH_PR"
84+
echo " $BASE_PR"
85+
echo " $SQUASH_PR"
86+
echo " $REWRITE_MESSAGE"
6587
if [[ $MERGE_MASTER == 1 ]]; then
66-
echo " $CHECKOUT_MASTER"
67-
echo " $CHERRY_PICK_PR"
68-
echo " $REWRITE_MESSAGE"
88+
echo " $CHECKOUT_MASTER && $CHERRY_PICK_PR"
6989
fi
7090
if [[ $MERGE_PATCH == 1 ]]; then
71-
echo " $CHECKOUT_PATCH"
72-
echo " $CHERRY_PICK_PR"
73-
echo " $REWRITE_MESSAGE"
91+
echo " $CHECKOUT_PATCH && $CHERRY_PICK_PR"
7492
fi
7593
echo " $PUSH_BRANCHES"
7694
echo " $RESTORE_BRANCH"
7795
echo "----------------------"
78-
96+
echo ">>> Fetch PR: $FETCH_PR"
7997
$FETCH_PR
98+
echo ">>> Mark base: $BASE_PR"
99+
$BASE_PR
100+
echo ">>> Autosquash: $SQUASH_PR"
101+
GIT_EDITOR=echo $SQUASH_PR
102+
echo ">>> Rewrite message: $REWRITE_MESSAGE"
103+
# Next line should work, but it errors, hence copy paste the command.
104+
# $REWRITE_MESSAGE
105+
git filter-branch -f --msg-filter "$BASEDIR/utils/github_closes.js $PR_NUMBER" merge_pr_base..merge_pr
80106
if [[ $MERGE_MASTER == 1 ]]; then
81107
echo
82-
echo ">>> Checkout master: $CHECKOUT_MASTER"
108+
echo ">>> Cherry pick to master: $CHECKOUT_MASTER && $CHERRY_PICK_PR"
83109
$CHECKOUT_MASTER
84-
echo
85-
echo ">>> Cherry pick pr: $CHERRY_PICK_PR"
86110
$CHERRY_PICK_PR
87-
echo
88-
echo ">>> Rewrite message: $REWRITE_MESSAGE"
89-
# Next line should work, but it errors, hence copy paste the command.
90-
# $REWRITE_MESSAGE
91-
git filter-branch -f --msg-filter "$BASEDIR/utils/github_closes.js $PR_NUMBER" HEAD~$PR_SHA_COUNT..HEAD
92-
93111
fi
94112
if [[ $MERGE_PATCH == 1 ]]; then
95113
echo
96-
echo ">>> Checkout $PATCH_BRANCH: $CHECKOUT_PATCH"
114+
echo ">>> Cherry pick to path: $CHECKOUT_PATCH && $CHERRY_PICK_PR"
97115
$CHECKOUT_PATCH
98-
echo
99-
echo ">>> Cherry pick pr: $CHERRY_PICK_PR"
100116
$CHERRY_PICK_PR
101-
echo
102-
echo ">>> Rewrite message: $REWRITE_MESSAGE"
103-
# Next line should work, but it errors, hence copy paste the command.
104-
# $REWRITE_MESSAGE
105-
git filter-branch -f --msg-filter "$BASEDIR/utils/github_closes.js $PR_NUMBER" HEAD~$PR_SHA_COUNT..HEAD
106117
fi
107118
$RESTORE_BRANCH
108119

109-
echo ">>> Push branches to angular repo"
110-
$PUSH_BRANCHES
120+
if [[ $PUSH_UPSTREAM == 1 ]]; then
121+
echo ">>> Push branches to angular repo"
122+
$PUSH_BRANCHES
123+
fi
111124
echo
112125
echo ">>>>>> SUCCESS <<<<<< PR#$PR_NUMBER merged."
113126

tools/validate-commit-message/validate-commit-message.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,35 @@ const fs = require('fs');
2020
const path = require('path');
2121
const configPath = path.resolve(__dirname, './commit-message.json');
2222
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
23-
const PATTERN = /^(revert\: )?(\w+)(?:\(([^)]+)\))?\: (.+)$/;
23+
const PATTERN = /^(\w+)(?:\(([^)]+)\))?\: (.+)$/;
24+
const FIXUP_SQUASH = /^(fixup|squash)\! /i;
25+
const REVERT = /^revert: (\"(.*)\"|(.*))?$/i;
2426

2527
module.exports = function(commitSubject) {
28+
commitSubject = commitSubject.replace(FIXUP_SQUASH, '');
29+
commitSubject = commitSubject.replace(REVERT, function(m, g1, g2, g3) { return g2 || g3; });
30+
2631
if (commitSubject.length > config['maxLength']) {
2732
error(`The commit message is longer than ${config['maxLength']} characters`, commitSubject);
2833
return false;
2934
}
3035

3136
const match = PATTERN.exec(commitSubject);
32-
if (!match || match[2] === 'revert') {
37+
if (!match) {
3338
error(
34-
`The commit message does not match the format of "<type>(<scope>): <subject> OR revert: type(<scope>): <subject>"`,
39+
`The commit message does not match the format of '<type>(<scope>): <subject>' OR 'Revert: "type(<scope>): <subject>"'`,
3540
commitSubject);
3641
return false;
3742
}
3843

39-
const type = match[2];
44+
const type = match[1];
4045
if (config['types'].indexOf(type) === -1) {
4146
error(
4247
`${type} is not an allowed type.\n => TYPES: ${config['types'].join(', ')}`, commitSubject);
4348
return false;
4449
}
4550

46-
const scope = match[3];
51+
const scope = match[2];
4752

4853
if (scope && !config['scopes'].includes(scope)) {
4954
error(

tools/validate-commit-message/validate-commit-message.spec.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
describe('validate-commit-message.js', function() {
1010
var validateMessage = require('./validate-commit-message');
1111
var SCOPES = validateMessage.config.scopes.join(', ');
12+
var TYPES = validateMessage.config.types.join(', ');
1213
var errors = [];
1314
var logs = [];
1415

@@ -40,6 +41,10 @@ describe('validate-commit-message.js', function() {
4041
expect(validateMessage('test(packaging): something')).toBe(VALID);
4142
expect(validateMessage('release: something')).toBe(VALID);
4243
expect(validateMessage('release(packaging): something')).toBe(VALID);
44+
expect(validateMessage('release(packaging): something')).toBe(VALID);
45+
expect(validateMessage('fixup! release(packaging): something')).toBe(VALID);
46+
expect(validateMessage('squash! release(packaging): something')).toBe(VALID);
47+
expect(validateMessage('Revert: "release(packaging): something"')).toBe(VALID);
4348
expect(errors).toEqual([]);
4449
});
4550

@@ -88,29 +93,32 @@ describe('validate-commit-message.js', function() {
8893

8994
expect(validateMessage(msg)).toBe(INVALID);
9095
expect(errors).toEqual([
91-
'INVALID COMMIT MSG: "not correct format"\n => ERROR: The commit message does not match the format of "<type>(<scope>): <subject> OR revert: type(<scope>): <subject>"'
96+
'INVALID COMMIT MSG: "not correct format"\n => ERROR: The commit message does not match the format of \'<type>(<scope>): <subject>\' OR \'Revert: "type(<scope>): <subject>"\''
9297
]);
9398
});
9499

95100

96-
it('should support "revert: type(scope):" syntax and reject "revert(scope):" syntax', function() {
97-
let correctMsg = 'revert: fix(compiler): reduce generated code payload size by 65%';
98-
expect(validateMessage(correctMsg)).toBe(VALID);
101+
it('should support "revert: type(scope):" syntax and reject "revert(scope):" syntax',
102+
function() {
103+
let correctMsg = 'revert: fix(compiler): reduce generated code payload size by 65%';
104+
expect(validateMessage(correctMsg)).toBe(VALID);
99105

100-
let incorretMsg = 'revert(compiler): reduce generated code payload size by 65%';
101-
expect(validateMessage(incorretMsg)).toBe(INVALID);
102-
expect(errors).toEqual([
103-
'INVALID COMMIT MSG: "revert(compiler): reduce generated code payload size by 65%"\n => ERROR: The commit message does not match the format of "<type>(<scope>): <subject> OR revert: type(<scope>): <subject>"'
104-
]);
105-
});
106+
let incorretMsg = 'revert(compiler): reduce generated code payload size by 65%';
107+
expect(validateMessage(incorretMsg)).toBe(INVALID);
108+
expect(errors).toEqual([
109+
'INVALID COMMIT MSG: "revert(compiler): reduce generated code payload size by 65%"\n' +
110+
' => ERROR: revert is not an allowed type.\n' +
111+
' => TYPES: ' + TYPES
112+
]);
113+
});
106114

107115

108116
it('should validate type', function() {
109117
expect(validateMessage('weird($filter): something')).toBe(INVALID);
110118
expect(errors).toEqual(
111119
['INVALID COMMIT MSG: "weird($filter): something"\n' +
112120
' => ERROR: weird is not an allowed type.\n' +
113-
' => TYPES: build, ci, docs, feat, fix, perf, refactor, release, style, test']);
121+
' => TYPES: ' + TYPES]);
114122
});
115123

116124

0 commit comments

Comments
 (0)