Skip to content

Commit 2d5970b

Browse files
committed
feat: add_oidc
1 parent 5c441a7 commit 2d5970b

File tree

9 files changed

+139
-47
lines changed

9 files changed

+139
-47
lines changed

.github/workflows/main.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ on: [pull_request]
33

44
jobs:
55
run:
6-
permissions: read-all
6+
permissions:
7+
id-token: write
8+
contents: read
79
runs-on: ${{ matrix.os }}
810
strategy:
911
fail-fast: false
@@ -24,6 +26,15 @@ jobs:
2426
flags: ${{ matrix.os }}
2527
verbose: true
2628
token: ${{ secrets.CODECOV_ORG_TOKEN }}
29+
- name: Upload test results to Codecov (calculator)
30+
uses: ./
31+
with:
32+
use_oidc: true
33+
fail_ci_if_error: true
34+
files: ./demo/calculator/junit.xml
35+
flags: ${{ matrix.os }}
36+
verbose: true
37+
token: ${{ secrets.CODECOV_ORG_TOKEN }}
2738
- name: Upload test results to Codecov (demo)
2839
uses: ./
2940
with:

README.md

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,42 +38,59 @@ steps:
3838
env:
3939
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
4040
```
41-
>**Note**: This assumes that you've set your Codecov token inside *Settings > Secrets* as `CODECOV_TOKEN`. If not, you can [get an upload token](https://docs.codecov.io/docs/frequently-asked-questions#section-where-is-the-repository-upload-token-found-) for your specific repo on [codecov.io](https://www.codecov.io). Keep in mind that secrets are *not* available to forks of repositories.
41+
> [!IMPORTANT]
42+
> This assumes that you've set your Codecov token inside *Settings > Secrets* as `CODECOV_TOKEN`. If not, you can [get an upload token](https://docs.codecov.io/docs/frequently-asked-questions#section-where-is-the-repository-upload-token-found-) for your specific repo on [codecov.io](https://www.codecov.io).
43+
> Keep in mind that secrets are *not* available to forks of repositories.
44+
> View more information on tokenless uploads [here](https://docs.codecov.com/docs/codecov-tokens#uploading-without-a-token).
45+
46+
> [!NOTE]
47+
> If you are using OIDC, you will need to set the `use_oidc` input to `true`, and make sure to add the following to your workflow file:
48+
> ```yaml
49+
> permissions:
50+
> id-token: write
51+
> contents: read
52+
> ...
53+
> steps:
54+
> - uses: codecov/test-results-action@v1
55+
> with:
56+
> use_oidc: true
57+
> ```
4258

4359
## Arguments
4460

4561
Codecov's Action supports inputs from the user. These inputs, along with their descriptions and usage contexts, are listed in the table below:
4662

4763
| Input | Description | Required |
4864
| :--- | :--- | :---: |
49-
| `token` | Repository Codecov token. Used to authorize report uploads | *Required
50-
| `binary` | The file location of a pre-downloaded version of the CLI. If specified, integrity checking will be bypassed. | Optional
51-
| `codecov_yml_path` | Specify the path to the Codecov YML | Optional
52-
| `commit_parent` | Override to specify the parent commit SHA | Optional
53-
| `directory` | Directory to search for test result reports. | Optional
54-
| `disable_search` | Disable search for test result files. This is helpful when specifying what files you want to upload with the --file option. | Optional
55-
| `dry_run` | Don't upload files to Codecov | Optional
56-
| `env_vars` | Environment variables to tag the upload with (e.g. PYTHON \| OS,PYTHON) | Optional
57-
| `exclude` | Folders to exclude from search | Optional
58-
| `fail_ci_if_error` | Specify whether or not CI build should fail if Codecov runs into an error during upload | Optional
59-
| `file` | Path to test result file to upload | Optional
60-
| `files` | Comma-separated list of files to upload | Optional
61-
| `flags` | Flag upload to group test results (e.g. py3.10 | py3.11 | py3.12) | Optional
62-
| `handle_no_reports_found` | Raise no exceptions when no test result reports found | Optional
63-
| `name` | User defined upload name. Visible in Codecov UI | Optional
64-
| `os` | Override the assumed OS. Options are linux \| macos \| windows \| . | Optional
65-
| `override_branch` | Specify the branch name | Optional
66-
| `override_build` | Specify the build number | Optional
67-
| `override_build_url` | The URL of the build where this is running | Optional
68-
| `override_commit` | Specify the commit SHA | Optional
69-
| `override_pr` | Specify the pull request number | Optional
70-
| `report_code` | The code of the report. If unsure, do not include | Optional
71-
| `root_dir` | Used when not in git/hg project to identify project root directory | Optional
72-
| `slug` | Specify the slug manually (Enterprise use) | Optional
73-
| `url` | Specify the base url to upload (Enterprise use) | Optional
74-
| `verbose` | Specify whether the Codecov output should be verbose | Optional
75-
| `version` | Specify which version of the Codecov CLI should be used. Defaults to `latest` | Optional
76-
| `working-directory` | Directory in which to execute codecov.sh | Optional
65+
| `token` | Repository Codecov token. Used to authorize report uploads | *Required
66+
| `binary` | The file location of a pre-downloaded version of the CLI. If specified, integrity checking will be bypassed. | Optional
67+
| `codecov_yml_path` | Specify the path to the Codecov YML | Optional
68+
| `commit_parent` | Override to specify the parent commit SHA | Optional
69+
| `directory` | Directory to search for test result reports. | Optional
70+
| `disable_search` | Disable search for test result files. This is helpful when specifying what files you want to upload with the --file option. | Optional
71+
| `dry_run` | Don't upload files to Codecov | Optional
72+
| `env_vars` | Environment variables to tag the upload with (e.g. PYTHON \| OS,PYTHON) | Optional
73+
| `exclude` | Folders to exclude from search | Optional
74+
| `fail_ci_if_error` | Specify whether or not CI build should fail if Codecov runs into an error during upload | Optional
75+
| `file` | Path to test result file to upload | Optional
76+
| `files` | Comma-separated list of files to upload | Optional
77+
| `flags` | Flag upload to group test results (e.g. py3.10 | py3.11 | py3.12) | Optional
78+
| `handle_no_reports_found` | Raise no exceptions when no test result reports found | Optional
79+
| `name` | User defined upload name. Visible in Codecov UI | Optional
80+
| `os` | Override the assumed OS. Options are linux \| macos \| windows \| . | Optional
81+
| `override_branch` | Specify the branch name | Optional
82+
| `override_build` | Specify the build number | Optional
83+
| `override_build_url` | The URL of the build where this is running | Optional
84+
| `override_commit` | Specify the commit SHA | Optional
85+
| `override_pr` | Specify the pull request number | Optional
86+
| `report_code` | The code of the report. If unsure, do not include | Optional
87+
| `root_dir` | Used when not in git/hg project to identify project root directory | Optional
88+
| `slug` | Specify the slug manually (Enterprise use) | Optional
89+
| `url` | Specify the base url to upload (Enterprise use) | Optional
90+
| `use_oidc` | Use OIDC to authenticate with Codecov | Optional
91+
| `verbose` | Specify whether the Codecov output should be verbose | Optional
92+
| `version` | Specify which version of the Codecov CLI should be used. Defaults to `latest` | Optional
93+
| `working-directory` | Directory in which to execute codecov.sh | Optional
7794

7895
### Example `workflow.yml` with Codecov Action
7996

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ inputs:
7777
url:
7878
description: 'Specify the base url to upload (Enterprise use)'
7979
required: false
80+
use_oidc:
81+
description: 'Use OIDC to authenticate with Codecov'
82+
required: false
8083
verbose:
8184
description: 'Specify whether the Codecov output should be verbose'
8285
required: false

dist/index.js

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32148,6 +32148,16 @@ const getCommand = (filename, generalArgs, command) => {
3214832148

3214932149
;// CONCATENATED MODULE: ./src/buildExec.ts
3215032150
/* eslint-disable @typescript-eslint/no-explicit-any */
32151+
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
32152+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
32153+
return new (P || (P = Promise))(function (resolve, reject) {
32154+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
32155+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
32156+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
32157+
step((generator = generator.apply(thisArg, _arguments || [])).next());
32158+
});
32159+
};
32160+
3215132161

3215232162

3215332163

@@ -32320,15 +32330,33 @@ const buildExecutionEnvironment = (token, envVars) => {
3232032330
}
3232132331
return uploadOptions;
3232232332
};
32323-
const buildExecutionOptions = (failCi, verbose) => {
32324-
const token = core.getInput('token');
32333+
const getToken = () => __awaiter(void 0, void 0, void 0, function* () {
32334+
let token = core.getInput('token');
32335+
let url = core.getInput('url');
32336+
const useOIDC = isTrue(core.getInput('use_oidc'));
32337+
if (useOIDC) {
32338+
if (!url) {
32339+
url = 'https://codecov.io';
32340+
}
32341+
try {
32342+
token = yield core.getIDToken(url);
32343+
return Promise.resolve(token);
32344+
}
32345+
catch (err) {
32346+
setFailure(`Codecov: Failed to get OIDC token with url: ${url}. ${err.message}`, true);
32347+
}
32348+
}
32349+
return token;
32350+
});
32351+
const buildExecutionOptions = (failCi, verbose) => __awaiter(void 0, void 0, void 0, function* () {
32352+
const token = yield getToken();
3232532353
const envVars = core.getInput('env_vars');
3232632354
const cleanedEnvVars = cleanEnvVars(envVars);
3232732355
const generalArgs = buildGeneralArgs(verbose);
3232832356
const { uploadExecArgs, uploadCommand } = buildUploadArgs(token, cleanedEnvVars, failCi);
3232932357
const executionEnvironment = buildExecutionEnvironment(token, cleanedEnvVars);
3233032358
return { generalArgs, uploadCommand, uploadExecArgs, executionEnvironment };
32331-
};
32359+
});
3233232360

3233332361

3233432362
;// CONCATENATED MODULE: external "node:child_process"
@@ -32342,7 +32370,7 @@ const external_node_path_namespaceObject = require("node:path");
3234232370
// EXTERNAL MODULE: ./node_modules/undici/index.js
3234332371
var undici = __nccwpck_require__(1773);
3234432372
;// CONCATENATED MODULE: ./src/validate.ts
32345-
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
32373+
var validate_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
3234632374
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3234732375
return new (P || (P = Promise))(function (resolve, reject) {
3234832376
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@@ -32358,7 +32386,7 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
3235832386

3235932387

3236032388

32361-
const verify = (filename, platform, version, verbose, failCi) => __awaiter(void 0, void 0, void 0, function* () {
32389+
const verify = (filename, platform, version, verbose, failCi) => validate_awaiter(void 0, void 0, void 0, function* () {
3236232390
try {
3236332391
const uploaderName = getUploaderName(platform);
3236432392
// Get SHASUM and SHASUM signature files
@@ -32375,8 +32403,8 @@ const verify = (filename, platform, version, verbose, failCi) => __awaiter(void
3237532403
console.log(`Received SHA256SUM signature ${shaSig}`);
3237632404
}
3237732405
yield external_node_fs_namespaceObject.writeFileSync(external_node_path_namespaceObject.join(__dirname, `${uploaderName}.SHA256SUM.sig`), shaSig);
32378-
const validateSha = () => __awaiter(void 0, void 0, void 0, function* () {
32379-
const calculateHash = (filename) => __awaiter(void 0, void 0, void 0, function* () {
32406+
const validateSha = () => validate_awaiter(void 0, void 0, void 0, function* () {
32407+
const calculateHash = (filename) => validate_awaiter(void 0, void 0, void 0, function* () {
3238032408
const stream = external_node_fs_namespaceObject.createReadStream(filename);
3238132409
const uploaderSha = external_node_crypto_namespaceObject.createHash(`sha256`);
3238232410
stream.pipe(uploaderSha);
@@ -32394,7 +32422,7 @@ const verify = (filename, platform, version, verbose, failCi) => __awaiter(void
3239432422
`uploader hash: ${hash}, public hash: ${shasum}`, failCi);
3239532423
}
3239632424
});
32397-
const verifySignature = () => __awaiter(void 0, void 0, void 0, function* () {
32425+
const verifySignature = () => validate_awaiter(void 0, void 0, void 0, function* () {
3239832426
const args = [
3239932427
'--logger-fd',
3240032428
'1',
@@ -32409,7 +32437,7 @@ const verify = (filename, platform, version, verbose, failCi) => __awaiter(void
3240932437
setFailure(`Codecov: Error verifying gpg signature: ${err.message}`, failCi);
3241032438
}
3241132439
});
32412-
const importKey = () => __awaiter(void 0, void 0, void 0, function* () {
32440+
const importKey = () => validate_awaiter(void 0, void 0, void 0, function* () {
3241332441
const args = [
3241432442
'--logger-fd',
3241532443
'1',
@@ -32484,7 +32512,7 @@ var src_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argu
3248432512

3248532513
let failCi;
3248632514
const invokeCLI = (filename, failCi, verbose) => src_awaiter(void 0, void 0, void 0, function* () {
32487-
const { generalArgs, uploadCommand, uploadExecArgs, executionEnvironment } = buildExecutionOptions(failCi, verbose);
32515+
const { generalArgs, uploadCommand, uploadExecArgs, executionEnvironment } = yield buildExecutionOptions(failCi, verbose);
3248832516
const doUploadTestResults = () => src_awaiter(void 0, void 0, void 0, function* () {
3248932517
yield exec.exec(getCommand(filename, generalArgs, uploadCommand).join(' '), uploadExecArgs, executionEnvironment);
3249032518
});

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

junit.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<testsuites name="jest tests" tests="2" failures="0" errors="0" time="0.962">
3+
<testsuite name="undefined" errors="0" failures="0" skipped="0" timestamp="2025-03-04T18:40:04" time="0.917" tests="2">
4+
<testcase classname=" test uncovered if" name=" test uncovered if" time="0.001">
5+
</testcase>
6+
<testcase classname=" fully covered" name=" fully covered" time="0">
7+
</testcase>
8+
</testsuite>
9+
</testsuites>

src/buildExec.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ describe('setting up cli invocation', () => {
6262
expect(uploaderVersion).toEqual('0.1.2');
6363
});
6464

65-
test('execution options', () => {
65+
test('execution options', async () => {
6666
const failCi = true;
6767
const verbose = false;
6868
const {generalArgs, uploadCommand, uploadExecArgs, executionEnvironment} =
69-
buildExecutionOptions(failCi, verbose);
69+
await buildExecutionOptions(failCi, verbose);
7070

7171
expect(uploadCommand).toEqual('do-upload');
7272

src/buildExec.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import {
88
getPlatform,
99
getUploaderName,
1010
} from './helpers';
11+
import {
12+
setFailure,
13+
} from './helpers';
1114

1215

1316
const context = github.context;
@@ -203,14 +206,35 @@ const buildExecutionEnvironment = (token: string, envVars) => {
203206
return uploadOptions;
204207
};
205208

206-
const buildExecutionOptions = (failCi: boolean, verbose: boolean) => {
207-
const token = core.getInput('token');
209+
const getToken = async (): Promise<string> => {
210+
let token = core.getInput('token');
211+
let url = core.getInput('url');
212+
const useOIDC = isTrue(core.getInput('use_oidc'));
213+
if (useOIDC) {
214+
if (!url) {
215+
url = 'https://codecov.io';
216+
}
217+
try {
218+
token = await core.getIDToken(url);
219+
return Promise.resolve(token);
220+
} catch (err) {
221+
setFailure(
222+
`Codecov: Failed to get OIDC token with url: ${url}. ${err.message}`,
223+
true,
224+
);
225+
}
226+
}
227+
return token;
228+
};
229+
230+
const buildExecutionOptions = async (failCi: boolean, verbose: boolean) => {
231+
const token = await getToken();
208232
const envVars = core.getInput('env_vars');
209233
const cleanedEnvVars = cleanEnvVars(envVars);
210234

211235
const generalArgs = buildGeneralArgs(verbose);
212236
const {uploadExecArgs, uploadCommand} =
213-
buildUploadArgs(token, cleanedEnvVars, failCi);
237+
buildUploadArgs(token, cleanedEnvVars, failCi);
214238
const executionEnvironment = buildExecutionEnvironment(token, cleanedEnvVars);
215239

216240
return {generalArgs, uploadCommand, uploadExecArgs, executionEnvironment};

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const invokeCLI = async (
2727
verbose: boolean,
2828
) => {
2929
const {generalArgs, uploadCommand, uploadExecArgs, executionEnvironment} =
30-
buildExecutionOptions(failCi, verbose);
30+
await buildExecutionOptions(failCi, verbose);
3131

3232
const doUploadTestResults = async () => {
3333
await exec.exec(

0 commit comments

Comments
 (0)