-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(circleci-orb): properly pass through revision parameters
The actual pipeline variables cannot be accessed directly from our Orb and we would need to pass them through explicitly. Also this cuts the first 0.0.1 version of the Orb for us in other repositories.
- Loading branch information
1 parent
5b747aa
commit 0f3a67f
Showing
8 changed files
with
234 additions
and
184 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
description: Rebase PR on the target branch | ||
|
||
parameters: | ||
head_revision: | ||
type: string | ||
description: The `pipeline.git.revision` pipeline value. | ||
base_revision: | ||
type: string | ||
description: The `pipeline.git.base_revision` pipeline value. | ||
primary_branch_name: | ||
type: string | ||
description: The primary branch for the repository. | ||
default: 'main' | ||
shell: | ||
type: string | ||
default: "" | ||
description: | | ||
Shell to use for executing the command. Useful for Windows where a | ||
non-bash shell is the default. | ||
steps: | ||
- run: | ||
environment: | ||
MAIN_BRANCH_NAME: << parameters.primary_branch_name >> | ||
CIRCLE_GIT_BASE_REVISION: << parameters.base_revision >> | ||
CIRCLE_GIT_HEAD_REVISION: << parameters.head_revision >> | ||
name: Rebasing PR on the target branch | ||
shell: << parameters.shell >> | ||
command: << include(../dist/bin/circleci-orb/scripts/rebase-pr-on-target-branch/script.sh) >> |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
circleci-orb/scripts/rebase-pr-on-target-branch/helpers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import {execSync as execSync_} from 'child_process'; | ||
import {getRefFromBranchList} from './ref-branch-list'; | ||
|
||
/** Synchronously executes the command, suppressing errors as empty string outputs. */ | ||
export function exec(command: string): string { | ||
try { | ||
return execSync_(command, {stdio: 'pipe', encoding: 'utf8'}).trim(); | ||
} catch (err: unknown) { | ||
return ''; | ||
} | ||
} | ||
|
||
/** | ||
* Get the list of branches which contain the provided sha, sorted in descending | ||
* order by committerdate. | ||
* | ||
* example: | ||
* upstream/main | ||
* upstream/9.0.x | ||
* upstream/test | ||
* upstream/1.1.x | ||
*/ | ||
export function getBranchListForSha(sha: string, remote: string) { | ||
return exec(`git branch -r '${remote}/*' --sort=-committerdate --contains ${sha}`); | ||
} | ||
|
||
/** Get the common ancestor sha of the two provided shas. */ | ||
export function getCommonAncestorSha(sha1: string, sha2: string) { | ||
return exec(`git merge-base ${sha1} ${sha2}`); | ||
} | ||
|
||
/** * Adds the remote to git, if it doesn't already exist. */ | ||
export function addAndFetchRemote(owner: string, name: string) { | ||
const remoteName = `${owner}_${name}`; | ||
exec(`git remote add ${remoteName} https://github.com/${owner}/${name}.git`); | ||
exec(`git fetch ${remoteName}`); | ||
return remoteName; | ||
} | ||
|
||
/** Get the full sha of the ref provided. */ | ||
export function getShaFromRef(ref: string) { | ||
return exec(`git rev-parse ${ref}`); | ||
} | ||
|
||
/** Get the ref and latest shas for the provided sha on a specific remote. */ | ||
export function lookupSha(sha: string, owner: string, name: string, primaryBranchName: string) { | ||
const remote = addAndFetchRemote(owner, name); | ||
// Get the ref on the remote for the sha provided. | ||
const ref = getRefFromBranchList(getBranchListForSha(sha, remote), primaryBranchName); | ||
// Get the latest sha on the discovered remote ref. | ||
const latestSha = getShaFromRef(`${remote}/${ref}`); | ||
|
||
return {remote, ref, latestSha, sha}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#!/usr/bin/env node | ||
|
||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import {exec, getCommonAncestorSha, lookupSha} from './helpers'; | ||
|
||
// Parameter variables. | ||
const baseRevision = process.env.CIRCLE_GIT_BASE_REVISION!; | ||
const headRevision = process.env.CIRCLE_GIT_HEAD_REVISION!; | ||
|
||
// CircleCI environment variables. | ||
const baseRepoOwner = process.env.CIRCLE_PROJECT_USERNAME!; | ||
const baseRepoName = process.env.CIRCLE_PROJECT_REPONAME!; | ||
const headRepoOwner = process.env.CIRCLE_PR_USERNAME!; | ||
const headRepoName = process.env.CIRCLE_PR_REPONAME!; | ||
const prNumber = process.env.CIRCLE_PR_NUMBER!; | ||
const primaryBranchName = process.env.MAIN_BRANCH_NAME!; | ||
|
||
if (!process.env.CIRCLE_PR_NUMBER) { | ||
console.info('Skipping rebase as the CircleCI run is not for a pull request.'); | ||
process.exit(0); | ||
} | ||
|
||
/** Rebase on the latest commit for the targeted branch. */ | ||
(async () => { | ||
const base = lookupSha(baseRevision, baseRepoOwner, baseRepoName, primaryBranchName); | ||
const target = lookupSha(headRevision, headRepoOwner, headRepoName, primaryBranchName); | ||
const commonAncestorSha = getCommonAncestorSha(base.sha, target.sha); | ||
|
||
// Log known refs and shas | ||
console.log(`--------------------------------`); | ||
console.log(` Target Branch: ${base.ref}`); | ||
console.log(` Latest Commit for Target Branch: ${target.latestSha}`); | ||
console.log(` Latest Commit for PR: ${base.latestSha}`); | ||
console.log(` First Common Ancestor SHA: ${commonAncestorSha}`); | ||
console.log(`--------------------------------`); | ||
console.log(); | ||
|
||
// Get the count of commits between the latest commit from origin and the common ancestor SHA. | ||
const commitCount = exec(`git rev-list --count origin/${base.ref}...${commonAncestorSha}`); | ||
console.log(`Checking ${commitCount} commits for changes in the CircleCI config file.`); | ||
|
||
// Check if the files changed between the latest commit from origin and the common ancestor SHA | ||
// includes the CircleCI config. | ||
const circleCIConfigChanged = exec( | ||
`git diff --name-only origin/${base.ref} ${commonAncestorSha} -- .circleci/config.yml`, | ||
); | ||
if (!!circleCIConfigChanged) { | ||
throw Error(` | ||
CircleCI config on ${base.ref} has been modified since commit | ||
${commonAncestorSha.slice(0, 7)}, which this PR is based on. | ||
Please rebase the PR on ${base.ref} after fetching from upstream. | ||
Rebase instructions for PR Author, please run the following commands: | ||
git fetch upstream ${base.ref}; | ||
git checkout ${target.ref}; | ||
git rebase upstream/${base.ref}; | ||
git push --force-with-lease; | ||
Angular team members can rebase this PR with the following command: | ||
yarn ng-dev pr rebase ${prNumber} | ||
`); | ||
} else { | ||
console.log('No change found in the CircleCI config file, continuing.'); | ||
} | ||
console.log(); | ||
|
||
// Rebase the PR. | ||
exec(`git rebase origin/${base.ref}`); | ||
console.log(`Rebased current branch onto ${base.ref}.`); | ||
})().catch((err: unknown) => { | ||
console.error('Failed to rebase on top of target branch.'); | ||
console.error(err); | ||
process.exitCode = 1; | ||
}); |
Oops, something went wrong.