Skip to content

Commit

Permalink
feat(action): fallback sha option
Browse files Browse the repository at this point in the history
  • Loading branch information
mandarini committed May 23, 2024
1 parent 0752207 commit c1031b9
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 51 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ jobs:
# Default: false
error-on-no-successful-workflow: ""

# Fallback SHA to use if no successful workflow run is found. This can be useful in scenarios where you need a specific commit as a reference for comparison, especially in newly set up repositories or those with sparse workflow runs.
#
# Default: ""
fallback-sha: ""

# The type of event to check for the last successful commit corresponding to that workflow-id, e.g. push, pull_request, release etc.
#
# Default: push
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ inputs:
error-on-no-successful-workflow:
description: "By default, if no successful workflow is found on the main branch to determine the SHA, we will log a warning and use HEAD~1. Enable this option to error and exit instead."
default: "false"
fallback-sha:
description: "Fallback SHA to use if no successful workflow run is found."
required: false
default: ""
last-successful-event:
description: "The type of event to check for the last successful commit corresponding to that workflow-id, e.g. push, pull_request, release etc"
default: "push"
Expand Down
34 changes: 22 additions & 12 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37867,6 +37867,7 @@ const errorOnNoSuccessfulWorkflow = process.argv[4];
const lastSuccessfulEvent = process.argv[5];
const workingDirectory = process.argv[6];
const workflowId = process.argv[7];
const fallbackSHA = process.argv[8];
const defaultWorkingDirectory = ".";
const ProxifiedClient = action_1.Octokit.plugin(proxyPlugin);
let BASE_SHA;
Expand Down Expand Up @@ -37913,17 +37914,23 @@ let BASE_SHA;
else {
process.stdout.write("\n");
process.stdout.write(`WARNING: Unable to find a successful workflow run on 'origin/${mainBranchName}', or the latest successful workflow was connected to a commit which no longer exists on that branch (e.g. if that branch was rebased)\n`);
process.stdout.write(`We are therefore defaulting to use HEAD~1 on 'origin/${mainBranchName}'\n`);
process.stdout.write("\n");
process.stdout.write(`NOTE: You can instead make this a hard error by setting 'error-on-no-successful-workflow' on the action in your workflow.\n`);
process.stdout.write("\n");
const commitCountOutput = (0, child_process_1.spawnSync)("git", ["rev-list", "--count", `origin/${mainBranchName}`], { encoding: "utf-8" }).stdout;
const commitCount = parseInt(stripNewLineEndings(commitCountOutput), 10);
const LAST_COMMIT_CMD = `origin/${mainBranchName}${commitCount > 1 ? "~1" : ""}`;
const baseRes = (0, child_process_1.spawnSync)("git", ["rev-parse", LAST_COMMIT_CMD], {
encoding: "utf-8",
});
BASE_SHA = baseRes.stdout;
if (fallbackSHA) {
BASE_SHA = fallbackSHA;
process.stdout.write(`Using provided fallback SHA: ${fallbackSHA}\n`);
}
else {
process.stdout.write(`We are therefore defaulting to use HEAD~1 on 'origin/${mainBranchName}'\n`);
process.stdout.write("\n");
process.stdout.write(`NOTE: You can instead make this a hard error by setting 'error-on-no-successful-workflow' on the action in your workflow.\n`);
process.stdout.write("\n");
const commitCountOutput = (0, child_process_1.spawnSync)("git", ["rev-list", "--count", `origin/${mainBranchName}`], { encoding: "utf-8" }).stdout;
const commitCount = parseInt(stripNewLineEndings(commitCountOutput), 10);
const LAST_COMMIT_CMD = `origin/${mainBranchName}${commitCount > 1 ? "~1" : ""}`;
const baseRes = (0, child_process_1.spawnSync)("git", ["rev-parse", LAST_COMMIT_CMD], {
encoding: "utf-8",
});
BASE_SHA = baseRes.stdout;
}
core.setOutput("noPreviousBuild", "true");
}
}
Expand Down Expand Up @@ -37977,7 +37984,10 @@ function findSuccessfulCommit(workflow_id, run_id, owner, repo, branch, lastSucc
owner,
repo,
// on some workflow runs we do not have branch property
branch: lastSuccessfulEvent === "push" || lastSuccessfulEvent === "workflow_dispatch" ? branch : undefined,
branch: lastSuccessfulEvent === "push" ||
lastSuccessfulEvent === "workflow_dispatch"
? branch
: undefined,
workflow_id,
event: lastSuccessfulEvent,
status: "success",
Expand Down
88 changes: 49 additions & 39 deletions find-successful-workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const errorOnNoSuccessfulWorkflow = process.argv[4];
const lastSuccessfulEvent = process.argv[5];
const workingDirectory = process.argv[6];
const workflowId = process.argv[7];
const fallbackSHA = process.argv[8];
const defaultWorkingDirectory = ".";

const ProxifiedClient = Octokit.plugin(proxyPlugin);
Expand All @@ -29,7 +30,7 @@ let BASE_SHA: string;
} else {
process.stdout.write("\n");
process.stdout.write(
`WARNING: Working directory '${workingDirectory}' doesn't exist.\n`
`WARNING: Working directory '${workingDirectory}' doesn't exist.\n`,
);
}
}
Expand All @@ -49,7 +50,7 @@ let BASE_SHA: string;
const baseResult = spawnSync(
"git",
["merge-base", `origin/${mainBranchName}`, mergeBaseRef],
{ encoding: "utf-8" }
{ encoding: "utf-8" },
);
BASE_SHA = baseResult.stdout;
} catch (e) {
Expand All @@ -64,7 +65,7 @@ let BASE_SHA: string;
owner,
repo,
mainBranchName,
lastSuccessfulEvent
lastSuccessfulEvent,
);
} catch (e) {
core.setFailed(e.message);
Expand All @@ -76,42 +77,47 @@ let BASE_SHA: string;
reportFailure(mainBranchName);
return;
} else {
process.stdout.write( "\n");
process.stdout.write(
`WARNING: Unable to find a successful workflow run on 'origin/${mainBranchName}', or the latest successful workflow was connected to a commit which no longer exists on that branch (e.g. if that branch was rebased)\n`
);
process.stdout.write(
`We are therefore defaulting to use HEAD~1 on 'origin/${mainBranchName}'\n`
);
process.stdout.write("\n");
process.stdout.write(
`NOTE: You can instead make this a hard error by setting 'error-on-no-successful-workflow' on the action in your workflow.\n`
`WARNING: Unable to find a successful workflow run on 'origin/${mainBranchName}', or the latest successful workflow was connected to a commit which no longer exists on that branch (e.g. if that branch was rebased)\n`,
);
process.stdout.write("\n");
if (fallbackSHA) {
BASE_SHA = fallbackSHA;
process.stdout.write(`Using provided fallback SHA: ${fallbackSHA}\n`);
} else {
process.stdout.write(
`We are therefore defaulting to use HEAD~1 on 'origin/${mainBranchName}'\n`,
);
process.stdout.write("\n");
process.stdout.write(
`NOTE: You can instead make this a hard error by setting 'error-on-no-successful-workflow' on the action in your workflow.\n`,
);
process.stdout.write("\n");

const commitCountOutput = spawnSync(
"git",
["rev-list", "--count", `origin/${mainBranchName}`],
{ encoding: "utf-8" }
).stdout;
const commitCount = parseInt(
stripNewLineEndings(commitCountOutput),
10
);
const commitCountOutput = spawnSync(
"git",
["rev-list", "--count", `origin/${mainBranchName}`],
{ encoding: "utf-8" },
).stdout;
const commitCount = parseInt(
stripNewLineEndings(commitCountOutput),
10,
);

const LAST_COMMIT_CMD = `origin/${mainBranchName}${
commitCount > 1 ? "~1" : ""
}`;
const baseRes = spawnSync("git", ["rev-parse", LAST_COMMIT_CMD], {
encoding: "utf-8",
});
BASE_SHA = baseRes.stdout;
const LAST_COMMIT_CMD = `origin/${mainBranchName}${
commitCount > 1 ? "~1" : ""
}`;
const baseRes = spawnSync("git", ["rev-parse", LAST_COMMIT_CMD], {
encoding: "utf-8",
});
BASE_SHA = baseRes.stdout;
}
core.setOutput("noPreviousBuild", "true");
}
} else {
process.stdout.write("\n");
process.stdout.write(
`Found the last successful workflow run on 'origin/${mainBranchName}'\n`
`Found the last successful workflow run on 'origin/${mainBranchName}'\n`,
);
process.stdout.write(`Commit: ${BASE_SHA}\n`);
}
Expand Down Expand Up @@ -148,7 +154,7 @@ async function findSuccessfulCommit(
owner: string,
repo: string,
branch: string,
lastSuccessfulEvent: string
lastSuccessfulEvent: string,
): Promise<string | undefined> {
const octokit = new ProxifiedClient();
if (!workflow_id) {
Expand All @@ -162,7 +168,7 @@ async function findSuccessfulCommit(
.then(({ data: { workflow_id } }) => workflow_id);
process.stdout.write("\n");
process.stdout.write(
`Workflow Id not provided. Using workflow '${workflow_id}'\n`
`Workflow Id not provided. Using workflow '${workflow_id}'\n`,
);
}
// fetch all workflow runs on a given repo/branch/workflow with push and success
Expand All @@ -173,14 +179,18 @@ async function findSuccessfulCommit(
owner,
repo,
// on some workflow runs we do not have branch property
branch: lastSuccessfulEvent === "push" || lastSuccessfulEvent === "workflow_dispatch" ? branch : undefined,
branch:
lastSuccessfulEvent === "push" ||
lastSuccessfulEvent === "workflow_dispatch"
? branch
: undefined,
workflow_id,
event: lastSuccessfulEvent,
status: "success",
}
},
)
.then(({ data: { workflow_runs } }) =>
workflow_runs.map((run: { head_sha: any }) => run.head_sha)
workflow_runs.map((run: { head_sha: any }) => run.head_sha),
);

return await findExistingCommit(octokit, branch, shas);
Expand All @@ -198,7 +208,7 @@ async function findMergeBaseRef(): Promise<string> {
function findMergeQueuePr(): string {
const { head_ref, base_sha } = github.context.payload.merge_group;
const result = new RegExp(
`^refs/heads/gh-readonly-queue/${mainBranchName}/pr-(\\d+)-${base_sha}$`
`^refs/heads/gh-readonly-queue/${mainBranchName}/pr-(\\d+)-${base_sha}$`,
).exec(head_ref);
return result ? result.at(1) : undefined;
}
Expand All @@ -213,7 +223,7 @@ async function findMergeQueueBranch(): Promise<string> {
const octokit = new ProxifiedClient();
const result = await octokit.request(
`GET /repos/${owner}/${repo}/pulls/${pull_number}`,
{ owner, repo, pull_number: +pull_number }
{ owner, repo, pull_number: +pull_number },
);
return result.data.head.ref;
}
Expand All @@ -224,7 +234,7 @@ async function findMergeQueueBranch(): Promise<string> {
async function findExistingCommit(
octokit: Octokit,
branchName: string,
shas: string[]
shas: string[],
): Promise<string | undefined> {
for (const commitSha of shas) {
if (await commitExists(octokit, branchName, commitSha)) {
Expand All @@ -240,7 +250,7 @@ async function findExistingCommit(
async function commitExists(
octokit: Octokit,
branchName: string,
commitSha: string
commitSha: string,
): Promise<boolean> {
try {
spawnSync("git", ["cat-file", "-e", commitSha], {
Expand All @@ -263,7 +273,7 @@ async function commitExists(
});

return commits.data.some(
(commit: { sha: string }) => commit.sha === commitSha
(commit: { sha: string }) => commit.sha === commitSha,
);
} catch {
return false;
Expand Down

0 comments on commit c1031b9

Please sign in to comment.