Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/oidc-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ jobs:
"repository": "${{ github.repository_owner }}/frogbot"
},
"token_spec": {
"username": "admin",
"scope": "applied-permissions/admin",
"audience": "*@*",
"expires_in": 1200
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ coverage
/testdata/vcsclientmock.go
/action/lib/src/*
/action/lib/test/*
/action/node_modules/
CLAUDE.md
.claude
5 changes: 3 additions & 2 deletions action/.husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ if [ "$(git status action --porcelain=v1)" ]; then
cd action || exit
npm i
npm prune --production
git add node_modules lib
fi
git add -f node_modules lib
npm i
fi
16 changes: 12 additions & 4 deletions action/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,14 +283,22 @@ class Utils {
};
const response = yield httpClient.post(exchangeUrl, data, additionalHeaders);
const responseString = yield response.readBody();
const responseJson = JSON.parse(responseString);
process.env.JF_ACCESS_TOKEN = responseJson.access_token;
if (responseJson.access_token) {
core.setSecret(responseJson.access_token);
const statusCode = response.message.statusCode;
if (!statusCode || statusCode < 200 || statusCode >= 300) {
throw new Error(`Token exchange failed with HTTP ${statusCode}: ${responseString}`);
}
const responseJson = JSON.parse(responseString);
if (responseJson.errors) {
throw new Error(`${JSON.stringify(responseJson.errors)}`);
}
if (responseJson.error) {
throw new Error(`${responseJson.error}${responseJson.error_description ? ': ' + responseJson.error_description : ''}`);
}
if (!responseJson.access_token) {
throw new Error(`Token exchange response is missing access_token. Full response: ${responseString}`);
}
core.setSecret(responseJson.access_token);
process.env.JF_ACCESS_TOKEN = responseJson.access_token;
});
}
}
Expand Down
20 changes: 16 additions & 4 deletions action/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,17 +262,29 @@ export class Utils {

const response: HttpClientResponse = await httpClient.post(exchangeUrl, data, additionalHeaders);
const responseString: string = await response.readBody();
const responseJson: TokenExchangeResponseData = JSON.parse(responseString);
process.env.JF_ACCESS_TOKEN = responseJson.access_token;
if (responseJson.access_token) {
core.setSecret(responseJson.access_token);
const statusCode: number | undefined = response.message.statusCode;
if (!statusCode || statusCode < 200 || statusCode >= 300) {
throw new Error(`Token exchange failed with HTTP ${statusCode}: ${responseString}`);
}
const responseJson: TokenExchangeResponseData = JSON.parse(responseString);
if (responseJson.errors) {
throw new Error(`${JSON.stringify(responseJson.errors)}`);
}
if (responseJson.error) {
throw new Error(
`${responseJson.error}${responseJson.error_description ? ': ' + responseJson.error_description : ''}`,
);
}
if (!responseJson.access_token) {
throw new Error(`Token exchange response is missing access_token. Full response: ${responseString}`);
}
core.setSecret(responseJson.access_token);
process.env.JF_ACCESS_TOKEN = responseJson.access_token;
}
}
export interface TokenExchangeResponseData {
access_token: string;
errors: string;
error: string;
error_description: string;
}
10 changes: 5 additions & 5 deletions action/test/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe('Frogbot Action Tests', () => {
afterEach(() => {
delete process.env.JF_ACCESS_TOKEN;
delete process.env.JF_USER;
delete process.env.PASSWORD;
delete process.env.JF_PASSWORD;
delete process.env.JF_GIT_PROVIDER;
delete process.env.JF_GIT_OWNER;
delete process.env.GITHUB_REPOSITORY_OWNER;
Expand Down Expand Up @@ -114,25 +114,25 @@ describe('Frogbot Action Tests', () => {

describe('Generate auth string', () => {
it('Should return an empty string if releasesRepo is falsy', () => {
const result = Utils.generateAuthString('');
const result: string = Utils.generateAuthString('');
expect(result).toBe('');
});

it('Should generate a Bearer token if accessToken is provided', () => {
process.env.JF_ACCESS_TOKEN = 'yourAccessToken';
const result = Utils.generateAuthString('yourReleasesRepo');
const result: string = Utils.generateAuthString('yourReleasesRepo');
expect(result).toBe('Bearer yourAccessToken');
});

it('Should generate a Basic token if username and password are provided', () => {
process.env.JF_USER = 'yourUsername';
process.env.JF_PASSWORD = 'yourPassword';
const result = Utils.generateAuthString('yourReleasesRepo');
const result: string = Utils.generateAuthString('yourReleasesRepo');
expect(result).toBe('Basic eW91clVzZXJuYW1lOnlvdXJQYXNzd29yZA==');
});

it('Should return an empty string if no credentials are provided', () => {
const result = Utils.generateAuthString('yourReleasesRepo');
const result: string = Utils.generateAuthString('yourReleasesRepo');
expect(result).toBe('');
});
});
Expand Down
Loading