Use await using for installation token cleanup
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
|||||||
v22.14.0
|
v24.3.0
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ const sharedConfig = {
|
|||||||
bundle: true,
|
bundle: true,
|
||||||
format: "esm",
|
format: "esm",
|
||||||
platform: "node",
|
platform: "node",
|
||||||
target: "node20",
|
target: "node24",
|
||||||
minify: false,
|
minify: false,
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
// Bundle all dependencies - GitHub Actions doesn't have node_modules
|
// Bundle all dependencies - GitHub Actions doesn't have node_modules
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import { reportErrorToComment } from "./utils/errorReport.ts";
|
|||||||
import {
|
import {
|
||||||
createOctokit,
|
createOctokit,
|
||||||
parseRepoContext,
|
parseRepoContext,
|
||||||
revokeGitHubInstallationToken,
|
|
||||||
setupGitHubInstallationToken,
|
setupGitHubInstallationToken,
|
||||||
} from "./utils/github.ts";
|
} from "./utils/github.ts";
|
||||||
import { setupGitAuth, setupGitConfig } from "./utils/setup.ts";
|
import { setupGitAuth, setupGitConfig } from "./utils/setup.ts";
|
||||||
@@ -54,7 +53,6 @@ export interface MainResult {
|
|||||||
|
|
||||||
// intermediate result types for deterministic context building
|
// intermediate result types for deterministic context building
|
||||||
interface GitHubSetup {
|
interface GitHubSetup {
|
||||||
token: string;
|
|
||||||
owner: string;
|
owner: string;
|
||||||
name: string;
|
name: string;
|
||||||
octokit: Octokit;
|
octokit: Octokit;
|
||||||
@@ -67,12 +65,12 @@ type ApiKeySetup =
|
|||||||
| { success: false; error: string };
|
| { success: false; error: string };
|
||||||
|
|
||||||
export async function main(inputs: Inputs): Promise<MainResult> {
|
export async function main(inputs: Inputs): Promise<MainResult> {
|
||||||
|
const timer = new Timer();
|
||||||
|
await using installationToken = await setupGitHubInstallationToken();
|
||||||
let mcpServerClose: (() => Promise<void>) | undefined;
|
let mcpServerClose: (() => Promise<void>) | undefined;
|
||||||
let payload: Payload | undefined;
|
let payload: Payload | undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const timer = new Timer();
|
|
||||||
|
|
||||||
// phase 1: parse and validate inputs
|
// phase 1: parse and validate inputs
|
||||||
payload = parsePayload(inputs);
|
payload = parsePayload(inputs);
|
||||||
Inputs.assert(inputs);
|
Inputs.assert(inputs);
|
||||||
@@ -80,7 +78,7 @@ export async function main(inputs: Inputs): Promise<MainResult> {
|
|||||||
|
|
||||||
// phase 2: fast setup (github + temp dir)
|
// phase 2: fast setup (github + temp dir)
|
||||||
const [githubSetup, sharedTempDir] = await Promise.all([
|
const [githubSetup, sharedTempDir] = await Promise.all([
|
||||||
initializeGitHub(),
|
initializeGitHub(installationToken.token),
|
||||||
createTempDirectory(),
|
createTempDirectory(),
|
||||||
]);
|
]);
|
||||||
timer.checkpoint("githubSetup");
|
timer.checkpoint("githubSetup");
|
||||||
@@ -108,9 +106,9 @@ export async function main(inputs: Inputs): Promise<MainResult> {
|
|||||||
// phase 5: parallel long-running operations (agent install + git auth)
|
// phase 5: parallel long-running operations (agent install + git auth)
|
||||||
const toolState: ToolState = {};
|
const toolState: ToolState = {};
|
||||||
const [cliPath] = await Promise.all([
|
const [cliPath] = await Promise.all([
|
||||||
installAgentCli({ agent, token: githubSetup.token }),
|
installAgentCli({ agent, token: installationToken.token }),
|
||||||
setupGitAuth({
|
setupGitAuth({
|
||||||
token: githubSetup.token,
|
token: installationToken.token,
|
||||||
owner: githubSetup.owner,
|
owner: githubSetup.owner,
|
||||||
name: githubSetup.name,
|
name: githubSetup.name,
|
||||||
payload: resolvedPayload,
|
payload: resolvedPayload,
|
||||||
@@ -157,7 +155,7 @@ export async function main(inputs: Inputs): Promise<MainResult> {
|
|||||||
const toolContext: ToolContext = {
|
const toolContext: ToolContext = {
|
||||||
owner: githubSetup.owner,
|
owner: githubSetup.owner,
|
||||||
name: githubSetup.name,
|
name: githubSetup.name,
|
||||||
githubInstallationToken: githubSetup.token,
|
githubInstallationToken: installationToken.token,
|
||||||
octokit: githubSetup.octokit,
|
octokit: githubSetup.octokit,
|
||||||
payload: resolvedPayload,
|
payload: resolvedPayload,
|
||||||
repo: githubSetup.repo,
|
repo: githubSetup.repo,
|
||||||
@@ -230,7 +228,6 @@ export async function main(inputs: Inputs): Promise<MainResult> {
|
|||||||
if (mcpServerClose) {
|
if (mcpServerClose) {
|
||||||
await mcpServerClose();
|
await mcpServerClose();
|
||||||
}
|
}
|
||||||
await revokeGitHubInstallationToken();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,10 +346,9 @@ export interface ToolState {
|
|||||||
/**
|
/**
|
||||||
* Initialize GitHub connection: token, octokit, repo data, settings
|
* Initialize GitHub connection: token, octokit, repo data, settings
|
||||||
*/
|
*/
|
||||||
async function initializeGitHub(): Promise<GitHubSetup> {
|
async function initializeGitHub(token: string): Promise<GitHubSetup> {
|
||||||
log.info(`🐸 Running pullfrog/action@${packageJson.version}...`);
|
log.info(`🐸 Running pullfrog/action@${packageJson.version}...`);
|
||||||
|
|
||||||
const token = await setupGitHubInstallationToken();
|
|
||||||
const { owner, name } = parseRepoContext();
|
const { owner, name } = parseRepoContext();
|
||||||
|
|
||||||
const octokit = createOctokit(token);
|
const octokit = createOctokit(token);
|
||||||
@@ -364,7 +360,6 @@ async function initializeGitHub(): Promise<GitHubSetup> {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
token,
|
|
||||||
owner,
|
owner,
|
||||||
name,
|
name,
|
||||||
octokit,
|
octokit,
|
||||||
|
|||||||
+12
-13
@@ -1,6 +1,7 @@
|
|||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { throttling } from "@octokit/plugin-throttling";
|
import { throttling } from "@octokit/plugin-throttling";
|
||||||
import { Octokit } from "@octokit/rest";
|
import { Octokit } from "@octokit/rest";
|
||||||
|
import assert from "node:assert/strict";
|
||||||
import { createSign } from "node:crypto";
|
import { createSign } from "node:crypto";
|
||||||
import { log } from "./cli.ts";
|
import { log } from "./cli.ts";
|
||||||
import { retry } from "./retry.ts";
|
import { retry } from "./retry.ts";
|
||||||
@@ -248,31 +249,29 @@ let githubInstallationToken: string | undefined;
|
|||||||
/**
|
/**
|
||||||
* Setup GitHub installation token for the action
|
* Setup GitHub installation token for the action
|
||||||
*/
|
*/
|
||||||
export async function setupGitHubInstallationToken(): Promise<string> {
|
export async function setupGitHubInstallationToken() {
|
||||||
|
assert(!githubInstallationToken, "GitHub installation token is already set.");
|
||||||
const acquiredToken = await acquireNewToken();
|
const acquiredToken = await acquireNewToken();
|
||||||
core.setSecret(acquiredToken);
|
core.setSecret(acquiredToken);
|
||||||
githubInstallationToken = acquiredToken;
|
githubInstallationToken = acquiredToken;
|
||||||
return acquiredToken;
|
return {
|
||||||
|
token: acquiredToken,
|
||||||
|
[Symbol.asyncDispose]() {
|
||||||
|
githubInstallationToken = undefined;
|
||||||
|
return revokeGitHubInstallationToken(acquiredToken);
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the GitHub installation token from memory
|
* Get the GitHub installation token from memory
|
||||||
*/
|
*/
|
||||||
export function getGitHubInstallationToken(): string {
|
export function getGitHubInstallationToken(): string {
|
||||||
if (!githubInstallationToken) {
|
assert(githubInstallationToken, "GitHub installation token not set. Call setupGitHubInstallationToken first.");
|
||||||
throw new Error("GitHub installation token not set. Call setupGitHubInstallationToken first.");
|
|
||||||
}
|
|
||||||
return githubInstallationToken;
|
return githubInstallationToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function revokeGitHubInstallationToken(): Promise<void> {
|
async function revokeGitHubInstallationToken(token: string): Promise<void> {
|
||||||
if (!githubInstallationToken) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const token = githubInstallationToken;
|
|
||||||
githubInstallationToken = undefined;
|
|
||||||
|
|
||||||
const apiUrl = process.env.GITHUB_API_URL || "https://api.github.com";
|
const apiUrl = process.env.GITHUB_API_URL || "https://api.github.com";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user