|
| 1 | +import * as core from "@actions/core"; |
1 | 2 | import * as fs from "fs"; |
| 3 | +import * as os from "os"; |
2 | 4 | import * as util from "util"; |
3 | 5 | import addressparser from "nodemailer/lib/addressparser/index.js"; |
| 6 | +import path from "path"; |
4 | 7 | import { ILintError, LintCommit } from "./commit-lint.js"; |
5 | 8 | import { commitExists, git, emptyTreeName } from "./git.js"; |
6 | 9 | import { GitNotes } from "./git-notes.js"; |
@@ -62,6 +65,68 @@ export class CIHelper { |
62 | 65 | this.urlRepo = `${this.urlBase}${this.config.repo.name}/`; |
63 | 66 | } |
64 | 67 |
|
| 68 | + public async setupGitHubAction(): Promise<void> { |
| 69 | + // help dugite realize where `git` is... |
| 70 | + const gitExecutable = os.type() === "Windows_NT" ? "git.exe" : "git"; |
| 71 | + const stripSuffix = `bin${path.sep}${gitExecutable}`; |
| 72 | + for (const gitPath of (process.env.PATH || "/") |
| 73 | + .split(path.delimiter) |
| 74 | + .map((p) => path.normalize(`${p}${path.sep}${gitExecutable}`)) |
| 75 | + // eslint-disable-next-line security/detect-non-literal-fs-filename |
| 76 | + .filter((p) => p.endsWith(`${path.sep}${stripSuffix}`) && fs.existsSync(p))) { |
| 77 | + process.env.LOCAL_GIT_DIRECTORY = gitPath.substring(0, gitPath.length - stripSuffix.length); |
| 78 | + // need to override GIT_EXEC_PATH, so that Dugite can find the `git-remote-https` executable, |
| 79 | + // see https://github.com/desktop/dugite/blob/v2.7.1/lib/git-environment.ts#L44-L64 |
| 80 | + // Also: We cannot use `await git(["--exec-path"]);` because that would use Dugite, which would |
| 81 | + // override `GIT_EXEC_PATH` and then `git --exec-path` would report _that_... |
| 82 | + process.env.GIT_EXEC_PATH = spawnSync("/usr/bin/git", ["--exec-path"]).stdout.toString("utf-8").trimEnd(); |
| 83 | + break; |
| 84 | + } |
| 85 | + |
| 86 | + // get the access tokens via the inputs of the GitHub Action |
| 87 | + this.setAccessToken(this.config.repo.owner, core.getInput("pr-repo-token")); |
| 88 | + this.setAccessToken(this.config.repo.baseOwner, core.getInput("upstream-repo-token")); |
| 89 | + if (this.config.repo.testOwner) { |
| 90 | + this.setAccessToken(this.config.repo.testOwner, core.getInput("test-repo-token")); |
| 91 | + } |
| 92 | + |
| 93 | + // eslint-disable-next-line security/detect-non-literal-fs-filename |
| 94 | + if (!fs.existsSync(this.workDir)) await git(["init", "--bare", "--initial-branch", "unused", this.workDir]); |
| 95 | + for (const [key, value] of [ |
| 96 | + ["gc.auto", "0"], |
| 97 | + ["remote.origin.url", `https://github.com/${this.config.repo.owner}/${this.config.repo.name}`], |
| 98 | + ["remote.origin.promisor", "true"], |
| 99 | + ["remote.origin.partialCloneFilter", "blob:none"], |
| 100 | + ]) { |
| 101 | + await git(["config", key, value], { workDir: this.workDir }); |
| 102 | + } |
| 103 | + console.time("fetch Git notes"); |
| 104 | + await git( |
| 105 | + [ |
| 106 | + "fetch", |
| 107 | + "--filter=blob:limit=1g", // let's fetch the notes with all of their blobs |
| 108 | + "--no-tags", |
| 109 | + "origin", |
| 110 | + "--depth=1", |
| 111 | + `+${GitNotes.defaultNotesRef}:${GitNotes.defaultNotesRef}`, |
| 112 | + ], |
| 113 | + { |
| 114 | + workDir: this.workDir, |
| 115 | + }, |
| 116 | + ); |
| 117 | + console.timeEnd("fetch Git notes"); |
| 118 | + this.gggNotesUpdated = true; |
| 119 | + // "Unshallow" the refs by fetching the shallow commits with a tree-less filter. |
| 120 | + // This is needed because Git will otherwise fall over left and right when trying |
| 121 | + // to determine merge bases with really old branches. |
| 122 | + const unshallow = async (workDir: string) => { |
| 123 | + console.time(`Making ${workDir} non-shallow`); |
| 124 | + console.log(await git(["fetch", "--filter=tree:0", "origin", "--unshallow"], { workDir })); |
| 125 | + console.timeEnd(`Making ${workDir} non-shallow`); |
| 126 | + }; |
| 127 | + await unshallow(this.workDir); |
| 128 | + } |
| 129 | + |
65 | 130 | public setAccessToken(repositoryOwner: string, token: string): void { |
66 | 131 | this.github.setAccessToken(repositoryOwner, token); |
67 | 132 | if (this.config.repo.owner === repositoryOwner) { |
|
0 commit comments