Skip to content

Instantly share code, notes, and snippets.

@sdjnes
Created June 12, 2023 11:20
Show Gist options
  • Save sdjnes/7b94876b23d45cfe8d57982c9472cd3a to your computer and use it in GitHub Desktop.
Save sdjnes/7b94876b23d45cfe8d57982c9472cd3a to your computer and use it in GitHub Desktop.
NX Set SHAs
const { Octokit } = require('@octokit/action');
const core = require('@actions/core');
const github = require('@actions/github');
const { execSync } = require('child_process');
const {
runId,
repo: { repo, owner },
eventName,
} = github.context;
const [
_node,
_filename,
githubToken,
baseBranchName,
branchName,
lastSuccessfulEvent,
headSha,
] = process.argv;
process.env.GITHUB_TOKEN = githubToken;
(async () => {
process.stdout.write(JSON.stringify(process.argv));
const HEAD_SHA =
headSha || execSync(`git rev-parse HEAD`, { encoding: 'utf-8' }).toString();
let BASE_SHA = await findSuccessfulCommit(
runId,
owner,
repo,
baseBranchName,
branchName,
lastSuccessfulEvent
);
// If no successful workflow run is found, use the branching point from the base branch
if (BASE_SHA) {
process.stdout.write(`
\n
Found successful run for this workflow. Using it as BASE_SHA
\n
`);
} else {
BASE_SHA = execSync(
`git merge-base origin/${baseBranchName} ${HEAD_SHA}`
).toString();
process.stdout.write(`
\n
No successful run for this workflow found on the branch ${branchName}.\n
Using the branching point between origin/${baseBranchName} and this branch's head ${HEAD_SHA}\n
BASE_SHA=${BASE_SHA}
\n
`);
}
const stripNewLineEndings = (sha) => sha.replace('\n', '');
core.setOutput('base', stripNewLineEndings(BASE_SHA));
core.setOutput('head', stripNewLineEndings(HEAD_SHA));
})();
async function findSuccessfulCommit(
run_id,
owner,
repo,
baseBranchName,
branchName,
lastSuccessfulEvent
) {
const octokit = new Octokit();
const workflowId = await octokit
.request(`GET /repos/${owner}/${repo}/actions/runs/${run_id}`, {
owner,
repo,
branch: baseBranchName,
run_id,
})
.then(({ data: { workflow_id } }) => workflow_id);
const shas = await octokit
.request(
`GET /repos/${owner}/${repo}/actions/workflows/${workflowId}/runs`,
{
owner,
repo,
branch: branchName,
workflowId,
event: lastSuccessfulEvent,
status: 'success',
}
)
.then(({ data: { workflow_runs } }) =>
workflow_runs.map((run) => run.head_sha)
);
return await findExistingCommit(shas);
}
/**
* Get first existing commit
* @param {string[]} commit_shas
* @returns {string?}
*/
async function findExistingCommit(shas) {
for (const commitSha of shas) {
if (await commitExists(commitSha)) {
return commitSha;
}
}
return undefined;
}
/**
* Check if given commit is valid
* @param {string} commitSha
* @returns {boolean}
*/
async function commitExists(commitSha) {
try {
execSync(`git cat-file -e ${commitSha}`, { stdio: ['pipe', 'pipe', null] });
return true;
} catch {
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment