From e2d6f01edcbbf17df47067be88e85122d2e5d7a2 Mon Sep 17 00:00:00 2001 From: EnviousSwan Date: Fri, 6 Sep 2024 17:47:06 +0100 Subject: [PATCH] Refresh token every 50 minutes --- src/action/main.ts | 6 +++--- src/modules/workspace.test.ts | 19 +++++++++++++++---- src/modules/workspace.ts | 19 +++++++++++++++++-- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/action/main.ts b/src/action/main.ts index e9f24e3c..910fa5a6 100644 --- a/src/action/main.ts +++ b/src/action/main.ts @@ -28,8 +28,8 @@ async function run(): Promise { const files: Files = {...fs, ...io} const inputs = Input.from(core, files, logger).all() const gitHubApiUrl = inputs.github.apiUrl.value - const gitHubToken = await gitHubAppToken(inputs.github.app, gitHubApiUrl, 'installation') ?? inputs.github.token.value - const octokit = getOctokit(gitHubToken, {baseUrl: gitHubApiUrl}) + const gitHubToken = async () => await gitHubAppToken(inputs.github.app, gitHubApiUrl, 'installation') ?? inputs.github.token.value + const octokit = getOctokit(await gitHubToken(), {baseUrl: gitHubApiUrl}) const github = GitHub.from(logger, octokit) const workspace = Workspace.from(logger, files, os, cache) @@ -114,7 +114,7 @@ async function gitHubAppToken(app: GitHubAppInfo | undefined, gitHubApiUrl: stri const response = type === 'app' ? await auth({type: 'app'}) - : (app.installation ? await auth({type: 'installation', installationId: app.installation.value}) : undefined) + : (app.installation ? await auth({type: 'installation', installationId: app.installation.value, refresh: true}) : undefined) return response?.token } diff --git a/src/modules/workspace.test.ts b/src/modules/workspace.test.ts index 1af4e83a..b2f072a8 100644 --- a/src/modules/workspace.test.ts +++ b/src/modules/workspace.test.ts @@ -58,7 +58,7 @@ test.after(() => { test('`Workspace.prepare()` → prepares the workspace', async t => { const {workspace, calls} = fixture() - await workspace.prepare('- owner/repo1\n- owner/repo2', '123', undefined) + await workspace.prepare('- owner/repo1\n- owner/repo2', async () => '123', undefined) const expected: string[] = [ 'mkdirP("/home/scala-steward")', @@ -80,7 +80,7 @@ test('`Workspace.prepare()` → prepares the workspace when using a GitHub App', key: mandatory('this-is-the-key'), } - await workspace.prepare('this will not be used', '123', gitHubAppInfo) + await workspace.prepare('this will not be used', async () => '123', gitHubAppInfo) const expected: string[] = [ 'mkdirP("/home/scala-steward")', @@ -103,7 +103,7 @@ test('`Workspace.prepare()` → uses the repos input when GitHub App is "auth on key: mandatory('this-is-the-key'), } - await workspace.prepare('- owner/repo', '123', gitHubAppInfo) + await workspace.prepare('- owner/repo', async () => '123', gitHubAppInfo) const expected: string[] = [ 'mkdirP("/home/scala-steward")', @@ -115,6 +115,18 @@ test('`Workspace.prepare()` → uses the repos input when GitHub App is "auth on t.deepEqual(calls, expected) }) +test('`Workspace.writeAskPass()` → writes a token to the askpass.sh', async t => { + const {workspace, calls} = fixture() + + await workspace.writeAskPass(async () => '123') + + const expected: string[] = [ + 'writeFileSync("/home/scala-steward/askpass.sh", "#!/bin/sh\n\necho \'123\'")', + ] + + t.deepEqual(calls, expected) +}) + test('`Workspace.remove()` → removes the workspace', async t => { const {workspace, calls} = fixture() @@ -189,4 +201,3 @@ test('`Workspace.saveWorkspaceCache()` → saves cache', async t => { t.deepEqual(calls, expected) }) - diff --git a/src/modules/workspace.ts b/src/modules/workspace.ts index 01c19ef1..1837f961 100644 --- a/src/modules/workspace.ts +++ b/src/modules/workspace.ts @@ -111,7 +111,7 @@ export class Workspace { * @param token The GitHub Token used to authenticate into GitHub. * @param gitHubAppInfo The GitHub App information as provided by the user. */ - async prepare(reposList: string, token: string, gitHubAppInfo: GitHubAppInfo | undefined): Promise { + async prepare(reposList: string, token: () => Promise, gitHubAppInfo: GitHubAppInfo | undefined): Promise { try { await this.files.mkdirP(this.directory) @@ -122,7 +122,12 @@ export class Workspace { this.files.writeFileSync(this.repos_md.value, reposList) } - this.files.writeFileSync(this.askpass_sh.value, `#!/bin/sh\n\necho '${token}'`) + await this.writeAskPass(token) + setInterval(async () => { + await this.writeAskPass(token) + this.logger.info('✓ GitHub Token refreshed') + }, 1000 * 60 * 50) + this.files.chmodSync(this.askpass_sh.value, 0o755) this.logger.info('✓ Scala Steward workspace created') @@ -139,6 +144,16 @@ export class Workspace { await this.files.rmRF(this.directory) } + /** + * Writes a GitHub Token to the git-ask-pass file + * + * @param fetchToken - A function that returns a Promise resolving to a new token string. + */ + async writeAskPass(fetchToken: () => Promise): Promise { + const token = await fetchToken() + this.files.writeFileSync(this.askpass_sh.value, `#!/bin/sh\n\necho '${token}'`) + } + /** * Gets the first eight characters of the SHA-256 hash value for the * provided file's contents.