Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4fa18d55c | ||
|
|
0c014070f9 |
1
dist/main.cjs
vendored
1
dist/main.cjs
vendored
@@ -10420,6 +10420,7 @@ async function main(appId2, privateKey2, owner2, repositories2, core2, createApp
|
|||||||
core2.setOutput("token", authentication.token);
|
core2.setOutput("token", authentication.token);
|
||||||
if (!skipTokenRevoke2) {
|
if (!skipTokenRevoke2) {
|
||||||
core2.saveState("token", authentication.token);
|
core2.saveState("token", authentication.token);
|
||||||
|
core2.setOutput("expiresAt", authentication.expiresAt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function getTokenFromOwner(request2, auth, parsedOwner) {
|
async function getTokenFromOwner(request2, auth, parsedOwner) {
|
||||||
|
|||||||
28
dist/post.cjs
vendored
28
dist/post.cjs
vendored
@@ -3003,12 +3003,28 @@ async function post(core2, request2) {
|
|||||||
core2.info("Token is not set");
|
core2.info("Token is not set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await request2("DELETE /installation/token", {
|
const expiresAt = core2.getState("expiresAt");
|
||||||
headers: {
|
if (expiresAt && tokenExpiresIn(expiresAt) < 0) {
|
||||||
authorization: `token ${token}`
|
core2.info("Token expired, skipping token revocation");
|
||||||
}
|
return;
|
||||||
});
|
}
|
||||||
core2.info("Token revoked");
|
try {
|
||||||
|
await request2("DELETE /installation/token", {
|
||||||
|
headers: {
|
||||||
|
authorization: `token ${token}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
core2.info("Token revoked");
|
||||||
|
} catch (error) {
|
||||||
|
core2.warning(
|
||||||
|
`Token revocation failed: ${error.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function tokenExpiresIn(expiresAt) {
|
||||||
|
const now = /* @__PURE__ */ new Date();
|
||||||
|
const expiresAtDate = new Date(expiresAt);
|
||||||
|
return Math.round((expiresAtDate.getTime() - now.getTime()) / 1e3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// lib/request.js
|
// lib/request.js
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ export async function main(
|
|||||||
// Make token accessible to post function (so we can invalidate it)
|
// Make token accessible to post function (so we can invalidate it)
|
||||||
if (!skipTokenRevoke) {
|
if (!skipTokenRevoke) {
|
||||||
core.saveState("token", authentication.token);
|
core.saveState("token", authentication.token);
|
||||||
|
core.setOutput("expiresAt", authentication.expiresAt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
32
lib/post.js
32
lib/post.js
@@ -21,11 +21,31 @@ export async function post(core, request) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await request("DELETE /installation/token", {
|
const expiresAt = core.getState("expiresAt");
|
||||||
headers: {
|
if (expiresAt && tokenExpiresIn(expiresAt) < 0) {
|
||||||
authorization: `token ${token}`,
|
core.info("Token expired, skipping token revocation");
|
||||||
},
|
return;
|
||||||
});
|
}
|
||||||
|
|
||||||
core.info("Token revoked");
|
try {
|
||||||
|
await request("DELETE /installation/token", {
|
||||||
|
headers: {
|
||||||
|
authorization: `token ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
core.info("Token revoked");
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Token revocation failed: ${error.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} expiresAt
|
||||||
|
*/
|
||||||
|
function tokenExpiresIn(expiresAt) {
|
||||||
|
const now = new Date();
|
||||||
|
const expiresAtDate = new Date(expiresAt);
|
||||||
|
|
||||||
|
return Math.round((expiresAtDate.getTime() - now.getTime()) / 1000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "create-github-app-token",
|
"name": "create-github-app-token",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.6.3",
|
"version": "1.6.4",
|
||||||
"description": "GitHub Action for creating a GitHub App Installation Access Token",
|
"description": "GitHub Action for creating a GitHub App Installation Access Token",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "esbuild main.js post.js --bundle --outdir=dist --out-extension:.js=.cjs --platform=node --target=node20.0.0",
|
"build": "esbuild main.js post.js --bundle --outdir=dist --out-extension:.js=.cjs --platform=node --target=node20.0.0",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ x3WQZRiXlWejSMUAHuMwXrhGlltF3lw83+xAjnqsVp75kGS6OH61
|
|||||||
// Mock installation access token request
|
// Mock installation access token request
|
||||||
const mockInstallationAccessToken =
|
const mockInstallationAccessToken =
|
||||||
"ghs_16C7e42F292c6912E7710c838347Ae178B4a"; // This token is invalidated. It’s from https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app.
|
"ghs_16C7e42F292c6912E7710c838347Ae178B4a"; // This token is invalidated. It’s from https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app.
|
||||||
|
const mockExpiresAt = "2016-07-11T22:14:10Z";
|
||||||
mockPool
|
mockPool
|
||||||
.intercept({
|
.intercept({
|
||||||
path: `/app/installations/${mockInstallationId}/access_tokens`,
|
path: `/app/installations/${mockInstallationId}/access_tokens`,
|
||||||
@@ -84,7 +85,7 @@ x3WQZRiXlWejSMUAHuMwXrhGlltF3lw83+xAjnqsVp75kGS6OH61
|
|||||||
})
|
})
|
||||||
.reply(
|
.reply(
|
||||||
201,
|
201,
|
||||||
{ token: mockInstallationAccessToken },
|
{ token: mockInstallationAccessToken, expires_at: mockExpiresAt },
|
||||||
{ headers: { "content-type": "application/json" } }
|
{ headers: { "content-type": "application/json" } }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
28
tests/post-revoke-token-fail-response.test.js
Normal file
28
tests/post-revoke-token-fail-response.test.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { MockAgent, setGlobalDispatcher } from "undici";
|
||||||
|
|
||||||
|
// state variables are set as environment variables with the prefix STATE_
|
||||||
|
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions
|
||||||
|
process.env.STATE_token = "secret123";
|
||||||
|
|
||||||
|
// 1 hour in the future, not expired
|
||||||
|
process.env.STATE_expiresAt = new Date(Date.now() + 1000 * 60 * 60).toISOString();
|
||||||
|
|
||||||
|
const mockAgent = new MockAgent();
|
||||||
|
|
||||||
|
setGlobalDispatcher(mockAgent);
|
||||||
|
|
||||||
|
// Provide the base url to the request
|
||||||
|
const mockPool = mockAgent.get("https://api.github.com");
|
||||||
|
|
||||||
|
// intercept the request
|
||||||
|
mockPool
|
||||||
|
.intercept({
|
||||||
|
path: "/installation/token",
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
authorization: "token secret123",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.reply(401);
|
||||||
|
|
||||||
|
await import("../post.js");
|
||||||
28
tests/post-token-expired.test.js
Normal file
28
tests/post-token-expired.test.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { MockAgent, setGlobalDispatcher } from "undici";
|
||||||
|
|
||||||
|
// state variables are set as environment variables with the prefix STATE_
|
||||||
|
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions
|
||||||
|
process.env.STATE_token = "secret123";
|
||||||
|
|
||||||
|
// 1 hour in the past, expired
|
||||||
|
process.env.STATE_expiresAt = new Date(Date.now() - 1000 * 60 * 60).toISOString();
|
||||||
|
|
||||||
|
const mockAgent = new MockAgent();
|
||||||
|
|
||||||
|
setGlobalDispatcher(mockAgent);
|
||||||
|
|
||||||
|
// Provide the base url to the request
|
||||||
|
const mockPool = mockAgent.get("https://api.github.com");
|
||||||
|
|
||||||
|
// intercept the request
|
||||||
|
mockPool
|
||||||
|
.intercept({
|
||||||
|
path: "/installation/token",
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
authorization: "token secret123",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.reply(204);
|
||||||
|
|
||||||
|
await import("../post.js");
|
||||||
@@ -4,6 +4,9 @@ import { MockAgent, setGlobalDispatcher } from "undici";
|
|||||||
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions
|
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions
|
||||||
process.env.STATE_token = "secret123";
|
process.env.STATE_token = "secret123";
|
||||||
|
|
||||||
|
// 1 hour in the future, not expired
|
||||||
|
process.env.STATE_expiresAt = new Date(Date.now() + 1000 * 60 * 60).toISOString();
|
||||||
|
|
||||||
const mockAgent = new MockAgent();
|
const mockAgent = new MockAgent();
|
||||||
|
|
||||||
setGlobalDispatcher(mockAgent);
|
setGlobalDispatcher(mockAgent);
|
||||||
|
|||||||
@@ -69,7 +69,9 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
␊
|
␊
|
||||||
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a`
|
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
|
␊
|
||||||
|
::set-output name=expiresAt::2016-07-11T22:14:10Z`
|
||||||
|
|
||||||
## main-token-get-owner-set-repo-set-to-many.test.js
|
## main-token-get-owner-set-repo-set-to-many.test.js
|
||||||
|
|
||||||
@@ -83,7 +85,9 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
␊
|
␊
|
||||||
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a`
|
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
|
␊
|
||||||
|
::set-output name=expiresAt::2016-07-11T22:14:10Z`
|
||||||
|
|
||||||
## main-token-get-owner-set-repo-set-to-one.test.js
|
## main-token-get-owner-set-repo-set-to-one.test.js
|
||||||
|
|
||||||
@@ -97,7 +101,9 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
␊
|
␊
|
||||||
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a`
|
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
|
␊
|
||||||
|
::set-output name=expiresAt::2016-07-11T22:14:10Z`
|
||||||
|
|
||||||
## main-token-get-owner-set-to-org-repo-unset.test.js
|
## main-token-get-owner-set-to-org-repo-unset.test.js
|
||||||
|
|
||||||
@@ -111,7 +117,9 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
␊
|
␊
|
||||||
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a`
|
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
|
␊
|
||||||
|
::set-output name=expiresAt::2016-07-11T22:14:10Z`
|
||||||
|
|
||||||
## main-token-get-owner-set-to-user-fail-response.test.js
|
## main-token-get-owner-set-to-user-fail-response.test.js
|
||||||
|
|
||||||
@@ -126,7 +134,9 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
␊
|
␊
|
||||||
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a`
|
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
|
␊
|
||||||
|
::set-output name=expiresAt::2016-07-11T22:14:10Z`
|
||||||
|
|
||||||
## main-token-get-owner-set-to-user-repo-unset.test.js
|
## main-token-get-owner-set-to-user-repo-unset.test.js
|
||||||
|
|
||||||
@@ -140,7 +150,9 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
␊
|
␊
|
||||||
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a`
|
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
|
␊
|
||||||
|
::set-output name=expiresAt::2016-07-11T22:14:10Z`
|
||||||
|
|
||||||
## main-token-get-owner-unset-repo-set.test.js
|
## main-token-get-owner-unset-repo-set.test.js
|
||||||
|
|
||||||
@@ -154,7 +166,9 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
␊
|
␊
|
||||||
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a`
|
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
|
␊
|
||||||
|
::set-output name=expiresAt::2016-07-11T22:14:10Z`
|
||||||
|
|
||||||
## main-token-get-owner-unset-repo-unset.test.js
|
## main-token-get-owner-unset-repo-unset.test.js
|
||||||
|
|
||||||
@@ -168,7 +182,29 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
␊
|
␊
|
||||||
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a`
|
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
|
||||||
|
␊
|
||||||
|
::set-output name=expiresAt::2016-07-11T22:14:10Z`
|
||||||
|
|
||||||
|
## post-revoke-token-fail-response.test.js
|
||||||
|
|
||||||
|
> stderr
|
||||||
|
|
||||||
|
''
|
||||||
|
|
||||||
|
> stdout
|
||||||
|
|
||||||
|
'::warning::Token revocation failed: '
|
||||||
|
|
||||||
|
## post-token-expired.test.js
|
||||||
|
|
||||||
|
> stderr
|
||||||
|
|
||||||
|
''
|
||||||
|
|
||||||
|
> stdout
|
||||||
|
|
||||||
|
'Token expired, skipping token revocation'
|
||||||
|
|
||||||
## post-token-set.test.js
|
## post-token-set.test.js
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user