Compare commits

..

2 Commits

Author SHA1 Message Date
semantic-release-bot
4821f52fa7 build(release): 2.0.4 [skip ci]
## [2.0.4](https://github.com/actions/create-github-app-token/compare/v2.0.3...v2.0.4) (2025-05-02)

### Bug Fixes

* permission input handling ([#243](https://github.com/actions/create-github-app-token/issues/243)) ([2950cbc](2950cbc446))
2025-05-02 18:44:32 +00:00
Parker Brown
2950cbc446 fix: permission input handling (#243)
This pull request fixes the handling of permissions inputs.

- Updated `getPermissionsFromInputs` in
`lib/get-permissions-from-inputs.js` to use hyphens
(`INPUT_PERMISSION-`) instead of underscores (`INPUT_PERMISSION_`) in
input keys, added a check to skip empty values, and clarified behavior
when no permissions are set.
- Added a `shouldRetry` function to retry requests when server errors
(HTTP status 500 or higher) occur in the `main` function in
`lib/main.js` to prevent unnecessary retries.
- Updated test cases in `tests/main-token-permissions-set.test.js` to
match the new input key format with hyphens.
- Added a default empty string for unset inputs (e.g.,
`INPUT_PERMISSION-ADMINISTRATION`) in `tests/main.js` to simulate the
behavior of the Actions runner.
- Updated snapshots in `tests/snapshots/index.js.md` to reflect the
updated hyphenated input keys in permissions.

---------

Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
2025-05-02 11:44:01 -07:00
9 changed files with 21 additions and 13 deletions

6
dist/main.cjs vendored
View File

@@ -42394,8 +42394,9 @@ function createAppAuth(options) {
// lib/get-permissions-from-inputs.js // lib/get-permissions-from-inputs.js
function getPermissionsFromInputs(env) { function getPermissionsFromInputs(env) {
return Object.entries(env).reduce((permissions2, [key, value]) => { return Object.entries(env).reduce((permissions2, [key, value]) => {
if (!key.startsWith("INPUT_PERMISSION_")) return permissions2; if (!key.startsWith("INPUT_PERMISSION-")) return permissions2;
const permission = key.slice("INPUT_PERMISSION_".length).toLowerCase(); if (!value) return permissions2;
const permission = key.slice("INPUT_PERMISSION-".length).toLowerCase();
if (permissions2 === void 0) { if (permissions2 === void 0) {
return { [permission]: value }; return { [permission]: value };
} }
@@ -42568,6 +42569,7 @@ async function main(appId2, privateKey2, owner2, repositories2, permissions2, co
permissions2 permissions2
), ),
{ {
shouldRetry: (error) => error.status >= 500,
onFailedAttempt: (error) => { onFailedAttempt: (error) => {
core3.info( core3.info(
`Failed to create token for "${parsedRepositoryNames.join( `Failed to create token for "${parsedRepositoryNames.join(

View File

@@ -7,9 +7,12 @@
*/ */
export function getPermissionsFromInputs(env) { export function getPermissionsFromInputs(env) {
return Object.entries(env).reduce((permissions, [key, value]) => { return Object.entries(env).reduce((permissions, [key, value]) => {
if (!key.startsWith("INPUT_PERMISSION_")) return permissions; if (!key.startsWith("INPUT_PERMISSION-")) return permissions;
if (!value) return permissions;
const permission = key.slice("INPUT_PERMISSION_".length).toLowerCase(); const permission = key.slice("INPUT_PERMISSION-".length).toLowerCase();
// Inherit app permissions if no permissions inputs are set
if (permissions === undefined) { if (permissions === undefined) {
return { [permission]: value }; return { [permission]: value };
} }

View File

@@ -89,6 +89,7 @@ export async function main(
permissions permissions
), ),
{ {
shouldRetry: (error) => error.status >= 500,
onFailedAttempt: (error) => { onFailedAttempt: (error) => {
core.info( core.info(
`Failed to create token for "${parsedRepositoryNames.join( `Failed to create token for "${parsedRepositoryNames.join(

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "create-github-app-token", "name": "create-github-app-token",
"version": "2.0.3", "version": "2.0.4",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "create-github-app-token", "name": "create-github-app-token",
"version": "2.0.3", "version": "2.0.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.11.1", "@actions/core": "^1.11.1",

View File

@@ -2,7 +2,7 @@
"name": "create-github-app-token", "name": "create-github-app-token",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "2.0.3", "version": "2.0.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 --packages=bundle", "build": "esbuild main.js post.js --bundle --outdir=dist --out-extension:.js=.cjs --platform=node --target=node20.0.0 --packages=bundle",

View File

@@ -2,6 +2,6 @@ import { test } from "./main.js";
// Verify `main` successfully sets permissions // Verify `main` successfully sets permissions
await test(() => { await test(() => {
process.env.INPUT_PERMISSION_ISSUES = `write`; process.env["INPUT_PERMISSION-ISSUES"] = `write`;
process.env.INPUT_PERMISSION_PULL_REQUESTS = `read`; process.env["INPUT_PERMISSION-PULL-REQUESTS"] = `read`;
}); });

View File

@@ -38,6 +38,8 @@ so0tiQKBgGQXZaxaXhYUcxYHuCkQ3V4Vsj3ezlM92xXlP32SGFm3KgFhYy9kATxw
Cax1ytZzvlrKLQyQFVK1COs2rHt7W4cJ7op7C8zXfsigXCiejnS664oAuX8sQZID Cax1ytZzvlrKLQyQFVK1COs2rHt7W4cJ7op7C8zXfsigXCiejnS664oAuX8sQZID
x3WQZRiXlWejSMUAHuMwXrhGlltF3lw83+xAjnqsVp75kGS6OH61 x3WQZRiXlWejSMUAHuMwXrhGlltF3lw83+xAjnqsVp75kGS6OH61
-----END RSA PRIVATE KEY-----`, -----END RSA PRIVATE KEY-----`,
// The Actions runner sets all inputs to empty strings if not set.
"INPUT_PERMISSION-ADMINISTRATION": "",
}; };
export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) {
@@ -61,7 +63,7 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) {
const owner = env.INPUT_OWNER ?? env.GITHUB_REPOSITORY_OWNER; const owner = env.INPUT_OWNER ?? env.GITHUB_REPOSITORY_OWNER;
const currentRepoName = env.GITHUB_REPOSITORY.split("/")[1]; const currentRepoName = env.GITHUB_REPOSITORY.split("/")[1];
const repo = encodeURIComponent( const repo = encodeURIComponent(
(env.INPUT_REPOSITORIES ?? currentRepoName).split(",")[0], (env.INPUT_REPOSITORIES ?? currentRepoName).split(",")[0]
); );
mockPool mockPool
@@ -77,7 +79,7 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) {
.reply( .reply(
200, 200,
{ id: mockInstallationId, app_slug: mockAppSlug }, { id: mockInstallationId, app_slug: mockAppSlug },
{ headers: { "content-type": "application/json" } }, { headers: { "content-type": "application/json" } }
); );
// Mock installation access token request // Mock installation access token request
@@ -98,7 +100,7 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) {
.reply( .reply(
201, 201,
{ token: mockInstallationAccessToken, expires_at: mockExpiresAt }, { token: mockInstallationAccessToken, expires_at: mockExpiresAt },
{ headers: { "content-type": "application/json" } }, { headers: { "content-type": "application/json" } }
); );
// Run the callback // Run the callback

View File

@@ -331,7 +331,7 @@ Generated by [AVA](https://avajs.dev).
--- REQUESTS ---␊ --- REQUESTS ---␊
GET /repos/actions/create-github-app-token/installation␊ GET /repos/actions/create-github-app-token/installation␊
POST /app/installations/123456/access_tokens␊ POST /app/installations/123456/access_tokens␊
{"repositories":["create-github-app-token"],"permissions":{"issues":"write","pull_requests":"read"}}` {"repositories":["create-github-app-token"],"permissions":{"issues":"write","pull-requests":"read"}}`
## post-revoke-token-fail-response.test.js ## post-revoke-token-fail-response.test.js

Binary file not shown.