Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix usage system parameters #243

Merged
merged 22 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from 19 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
40 changes: 33 additions & 7 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,9 @@ class Utils {
const exchangeUrl = jfrogCredentials.jfrogUrl.replace(/\/$/, '') + '/access/api/v1/oidc/token';
core.debug('Exchanging GitHub JSON web token with a JFrog access token...');
let projectKey = process.env.JF_PROJECT || '';
let jobId = process.env.GITHUB_JOB || '';
let jobId = this.getGithubJobId();
let runId = process.env.GITHUB_RUN_ID || '';
let githubRepository = process.env.GITHUB_REPOSITORY || '';
const httpClient = new http_client_1.HttpClient();
const data = `{
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
Expand All @@ -202,11 +203,13 @@ class Utils {
"project_key": "${projectKey}",
"gh_job_id": "${jobId}",
"gh_run_id": "${runId}",
"gh_repo": "${githubRepository}",
"application_key": "${applicationKey}"
}`;
const additionalHeaders = {
'Content-Type': 'application/json',
};
core.info('Data sent to token exchange: ' + data);
EyalDelarea marked this conversation as resolved.
Show resolved Hide resolved
const response = yield httpClient.post(exchangeUrl, data, additionalHeaders);
const responseString = yield response.readBody();
const responseJson = JSON.parse(responseString);
Expand Down Expand Up @@ -825,13 +828,16 @@ class Utils {
}
static getUsageBadge() {
const platformUrl = Utils.getPlatformUrl();
const githubJobId = Utils.encodeForUrl(process.env.GITHUB_JOB || '');
const gitRepo = Utils.encodeForUrl(process.env.GITHUB_REPOSITORY || '');
const githubJobId = this.getGithubJobId();
const gitRepo = process.env.GITHUB_REPOSITORY || '';
const runId = process.env.GITHUB_RUN_ID || '';
return `![](${platformUrl}ui/api/v1/u?s=1&m=1&job_id=${githubJobId}&run_id=${runId}&git_repo=${gitRepo})`;
}
static encodeForUrl(value) {
return encodeURIComponent(value);
const url = new URL(`${platformUrl}ui/api/v1/u`);
url.searchParams.set(Utils.SOURCE_PARAM_KEY, Utils.SOURCE_PARAM_VALUE);
url.searchParams.set(Utils.METRIC_PARAM_KEY, Utils.METRIC_PARAM_VALUE);
url.searchParams.set(Utils.JOB_ID_PARAM_KEY, githubJobId);
url.searchParams.set(Utils.RUN_ID_PARAM_KEY, runId);
url.searchParams.set(Utils.GIT_REPO_PARAM_KEY, gitRepo);
return `![](${url.toString()})`;
}
/**
* Checks if the header image is accessible via the internet.
Expand Down Expand Up @@ -872,6 +878,14 @@ class Utils {
}
return tempDir;
}
/**
* Retrieves the GitHub workflow name from the environment variables and URL encodes it.
* Note: To avoid confusion, this returns the workflow name, which we consider as job_id,
* whereas GitHub uses job_id to refer to the specific job within a workflow.
*/
static getGithubJobId() {
return process.env.GITHUB_WORKFLOW || '';
}
}
exports.Utils = Utils;
// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand Down Expand Up @@ -939,3 +953,15 @@ Utils.CUSTOM_SERVER_ID = 'custom-server-id';
Utils.MARKDOWN_HEADER_PNG_URL = 'https://media.jfrog.com/wp-content/uploads/2024/09/02161430/jfrog-job-summary.svg';
// Flag to indicate if the summary header is accessible, can be undefined if not checked yet.
Utils.isSummaryHeaderAccessible = undefined;
// Job ID query parameter key
Utils.JOB_ID_PARAM_KEY = 'job_id';
// Run ID query parameter key
Utils.RUN_ID_PARAM_KEY = 'run_id';
// Git repository query parameter key
Utils.GIT_REPO_PARAM_KEY = 'git_repo';
// Source query parameter indicating the source of the request
Utils.SOURCE_PARAM_KEY = 's';
Utils.SOURCE_PARAM_VALUE = '1';
// Metric query parameter indicating the metric type
Utils.METRIC_PARAM_KEY = 'm';
Utils.METRIC_PARAM_VALUE = '1';
43 changes: 34 additions & 9 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ export class Utils {
private static MARKDOWN_HEADER_PNG_URL: string = 'https://media.jfrog.com/wp-content/uploads/2024/09/02161430/jfrog-job-summary.svg';
// Flag to indicate if the summary header is accessible, can be undefined if not checked yet.
private static isSummaryHeaderAccessible: boolean | undefined = undefined;
// Job ID query parameter key
private static readonly JOB_ID_PARAM_KEY: string = 'job_id';
// Run ID query parameter key
private static readonly RUN_ID_PARAM_KEY: string = 'run_id';
// Git repository query parameter key
private static readonly GIT_REPO_PARAM_KEY: string = 'git_repo';
// Source query parameter indicating the source of the request
private static readonly SOURCE_PARAM_KEY: string = 's';
private static readonly SOURCE_PARAM_VALUE: string = '1';
// Metric query parameter indicating the metric type
private static readonly METRIC_PARAM_KEY: string = 'm';
private static readonly METRIC_PARAM_VALUE: string = '1';

/**
* Retrieves server credentials for accessing JFrog's server
Expand Down Expand Up @@ -234,8 +246,9 @@ export class Utils {
core.debug('Exchanging GitHub JSON web token with a JFrog access token...');

let projectKey: string = process.env.JF_PROJECT || '';
let jobId: string = process.env.GITHUB_JOB || '';
let jobId: string = this.getGithubJobId();
let runId: string = process.env.GITHUB_RUN_ID || '';
let githubRepository: string = process.env.GITHUB_REPOSITORY || '';

const httpClient: HttpClient = new HttpClient();
const data: string = `{
Expand All @@ -246,13 +259,14 @@ export class Utils {
"project_key": "${projectKey}",
"gh_job_id": "${jobId}",
"gh_run_id": "${runId}",
"gh_repo": "${githubRepository}",
"application_key": "${applicationKey}"
}`;

const additionalHeaders: OutgoingHttpHeaders = {
'Content-Type': 'application/json',
};

core.info('Data sent to token exchange: ' + data);
const response: HttpClientResponse = await httpClient.post(exchangeUrl, data, additionalHeaders);
const responseString: string = await response.readBody();
const responseJson: TokenExchangeResponseData = JSON.parse(responseString);
Expand Down Expand Up @@ -912,15 +926,17 @@ export class Utils {

static getUsageBadge(): string {
const platformUrl: string = Utils.getPlatformUrl();
const githubJobId: string = Utils.encodeForUrl(process.env.GITHUB_JOB || '');
const gitRepo: string = Utils.encodeForUrl(process.env.GITHUB_REPOSITORY || '');
const githubJobId: string = this.getGithubJobId();
const gitRepo: string = process.env.GITHUB_REPOSITORY || '';
const runId: string = process.env.GITHUB_RUN_ID || '';
const url: URL = new URL(`${platformUrl}ui/api/v1/u`);

return `![](${platformUrl}ui/api/v1/u?s=1&m=1&job_id=${githubJobId}&run_id=${runId}&git_repo=${gitRepo})`;
}

private static encodeForUrl(value: string): string {
return encodeURIComponent(value);
url.searchParams.set(Utils.SOURCE_PARAM_KEY, Utils.SOURCE_PARAM_VALUE);
url.searchParams.set(Utils.METRIC_PARAM_KEY, Utils.METRIC_PARAM_VALUE);
url.searchParams.set(Utils.JOB_ID_PARAM_KEY, githubJobId);
url.searchParams.set(Utils.RUN_ID_PARAM_KEY, runId);
url.searchParams.set(Utils.GIT_REPO_PARAM_KEY, gitRepo);
return `![](${url.toString()})`;
}

/**
Expand Down Expand Up @@ -959,6 +975,15 @@ export class Utils {
}
return tempDir;
}

/**
* Retrieves the GitHub workflow name from the environment variables and URL encodes it.
* Note: To avoid confusion, this returns the workflow name, which we consider as job_id,
* whereas GitHub uses job_id to refer to the specific job within a workflow.
*/
static getGithubJobId(): string {
return process.env.GITHUB_WORKFLOW || '';
}
}

export interface DownloadDetails {
Expand Down
24 changes: 16 additions & 8 deletions test/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -568,36 +568,44 @@ describe('setUsageEnvVars', () => {
});
});

describe('Utils', () => {
describe('Test correct encoding of badge URL', () => {
describe('getUsageBadge', () => {
beforeEach(() => {
process.env.JF_URL = 'https://example.jfrog.io/';
process.env.GITHUB_JOB = 'test-job';
process.env.GITHUB_REPOSITORY = 'test/repo';
process.env.GITHUB_RUN_ID = '123';
});

afterEach(() => {
delete process.env.JF_URL;
delete process.env.GITHUB_JOB;
delete process.env.GITHUB_WORKFLOW;
delete process.env.GITHUB_REPOSITORY;
delete process.env.GITHUB_RUN_ID;
});

it('should return the correct usage badge URL', () => {
process.env.GITHUB_WORKFLOW = 'test-job';
process.env.GITHUB_REPOSITORY = 'test/repo';
const expectedBadge: string = '![](https://example.jfrog.io/ui/api/v1/u?s=1&m=1&job_id=test-job&run_id=123&git_repo=test%2Frepo)';
expect(Utils.getUsageBadge()).toBe(expectedBadge);
});

it('should URL encode the job ID and repository', () => {
process.env.GITHUB_JOB = 'test job';
it('should URL encode the job ID and repository with spaces', () => {
process.env.GITHUB_WORKFLOW = 'test job';
process.env.GITHUB_REPOSITORY = 'test repo';
const expectedBadge: string = '![](https://example.jfrog.io/ui/api/v1/u?s=1&m=1&job_id=test%20job&run_id=123&git_repo=test%20repo)';
const expectedBadge: string = '![](https://example.jfrog.io/ui/api/v1/u?s=1&m=1&job_id=test+job&run_id=123&git_repo=test+repo)';
expect(Utils.getUsageBadge()).toBe(expectedBadge);
});

it('should URL encode the job ID and repository with special characters', () => {
process.env.GITHUB_WORKFLOW = 'test/job@workflow';
process.env.GITHUB_REPOSITORY = 'test/repo@special';
const expectedBadge: string =
'![](https://example.jfrog.io/ui/api/v1/u?s=1&m=1&job_id=test%2Fjob%40workflow&run_id=123&git_repo=test%2Frepo%40special)';
expect(Utils.getUsageBadge()).toBe(expectedBadge);
});

it('should handle missing environment variables gracefully', () => {
delete process.env.GITHUB_JOB;
delete process.env.GITHUB_WORKFLOW;
delete process.env.GITHUB_REPOSITORY;
const expectedBadge: string = '![](https://example.jfrog.io/ui/api/v1/u?s=1&m=1&job_id=&run_id=123&git_repo=)';
expect(Utils.getUsageBadge()).toBe(expectedBadge);
Expand Down
Loading