Skip to content

Commit 9b04055

Browse files
meorphismeorphis
andauthored
fix: add refresh for OIDC token (#165)
* increase oidc token expiration * lint * biuld * expires_in * refresh * private fn * clean up --------- Co-authored-by: meorphis <eric@stainless.com>
1 parent a937e1f commit 9b04055

7 files changed

Lines changed: 98 additions & 35 deletions

File tree

dist/build.js

Lines changed: 16 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js

Lines changed: 19 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/merge.js

Lines changed: 16 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/preview.js

Lines changed: 16 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/compat/index.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
import { getInput, getBooleanInput } from "./input";
2020
import { setOutput } from "./output";
2121
import { logger } from "../logger";
22+
import Stainless from "@stainless-api/sdk";
2223

2324
export {
2425
isGitLabCI,
@@ -115,11 +116,14 @@ export function getRunUrl() {
115116
: `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
116117
}
117118

118-
export async function getStainlessAuthToken(): Promise<string> {
119+
async function getStainlessAuthToken(): Promise<{
120+
key: string;
121+
expiresInSeconds: number | null;
122+
}> {
119123
const apiKey = getInput("stainless_api_key", { required: isGitLabCI() });
120124
if (apiKey) {
121125
logger.debug("Authenticating with provided Stainless API key");
122-
return apiKey;
126+
return { key: apiKey, expiresInSeconds: null };
123127
}
124128

125129
logger.debug("Authenticating with GitHub OIDC");
@@ -144,7 +148,8 @@ export async function getStainlessAuthToken(): Promise<string> {
144148
if (!data.value) {
145149
throw new Error("No token in OIDC response");
146150
}
147-
return data.value;
151+
// GitHub OIDC tokens expire after 5 minutes (this is not configurable as far as we can tell)
152+
return { key: data.value, expiresInSeconds: 300 };
148153
} catch (error) {
149154
throw new Error(
150155
`Failed to authenticate with GitHub OIDC. Make sure your workflow has 'id-token: write' permission ` +
@@ -247,3 +252,18 @@ class GitLabCommentClient implements CommentClient {
247252
});
248253
}
249254
}
255+
256+
export const setApiKey = async (stainless: Stainless) => {
257+
const { key: apiKey, expiresInSeconds } = await getStainlessAuthToken();
258+
stainless.apiKey = apiKey;
259+
260+
if (expiresInSeconds !== null) {
261+
setTimeout(
262+
() => {
263+
logger.info("Stainless auth token expired, setting new key");
264+
setApiKey(stainless);
265+
},
266+
(expiresInSeconds - 30) * 1000,
267+
); // Refresh 30 seconds before expiry
268+
}
269+
};

src/index.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Stainless from "@stainless-api/sdk";
22
import { getStainlessClient } from "./stainless";
33
import { readFileSync, writeFileSync } from "node:fs";
44
import YAML from "yaml";
5-
import { getBooleanInput, getInput, getStainlessAuthToken } from "./compat";
5+
import { getBooleanInput, getInput, setApiKey } from "./compat";
66
import { logger } from "./logger";
77

88
// https://www.conventionalcommits.org/en/v1.0.0/
@@ -16,7 +16,6 @@ export const isValidConventionalCommitMessage = (message: string) => {
1616

1717
export async function main() {
1818
// inputs
19-
const stainless_api_key = await getStainlessAuthToken();
2019
const inputPath = getInput("input_path", { required: true });
2120
const configPath = getInput("config_path", { required: false });
2221
let projectName = getInput("project_name", { required: false });
@@ -40,9 +39,8 @@ export async function main() {
4039
}
4140

4241
if (!projectName) {
43-
const stainless = getStainlessClient("index", {
44-
apiKey: stainless_api_key,
45-
});
42+
const stainless = getStainlessClient("index", {});
43+
await setApiKey(stainless);
4644
const projects = await stainless.projects.list({ limit: 2 });
4745
if (projects.data.length === 0) {
4846
const errorMsg = "No projects found. Please create a project first.";
@@ -65,7 +63,6 @@ export async function main() {
6563
const response = await uploadSpecAndConfig(
6664
inputPath,
6765
configPath,
68-
stainless_api_key,
6966
projectName,
7067
commitMessage,
7168
guessConfig,
@@ -102,7 +99,6 @@ export async function main() {
10299
async function uploadSpecAndConfig(
103100
specPath: string,
104101
configPath: string | undefined,
105-
token: string,
106102
projectName: string,
107103
commitMessage: string | undefined,
108104
guessConfig: boolean,
@@ -116,9 +112,9 @@ async function uploadSpecAndConfig(
116112
decoratedSpec: string | null;
117113
}> {
118114
const stainless = getStainlessClient("index", {
119-
apiKey: token,
120115
project: projectName,
121116
});
117+
await setApiKey(stainless);
122118
const specContent = readFileSync(specPath, "utf8");
123119

124120
let configContent;

src/wrapAction.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Stainless from "@stainless-api/sdk";
22
import { getInput } from "./compat/input";
3-
import { getStainlessAuthToken } from "./compat";
3+
import { setApiKey } from "./compat";
44
import { getStainlessClient } from "./stainless";
55
import { logger } from "./logger";
66

@@ -27,12 +27,13 @@ export function wrapAction(
2727

2828
try {
2929
projectName = getInput("project", { required: true });
30-
const apiKey = await getStainlessAuthToken();
3130
stainless = getStainlessClient(actionType, {
3231
project: projectName,
33-
apiKey,
3432
logLevel: "warn",
3533
});
34+
35+
await setApiKey(stainless);
36+
3637
await fn(stainless);
3738
await maybeReportResult({
3839
stainless,

0 commit comments

Comments
 (0)