-
Notifications
You must be signed in to change notification settings - Fork 0
feat(test): add standalone junit2jira action #105
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
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| # Convert JUnit test failures into Jira tickets | ||
|
|
||
| Scans a directory of JUnit XML reports and creates (or deduplicates) Jira issues | ||
| for test failures using [`junit2jira`](https://github.com/stackrox/junit2jira). | ||
| Optionally uploads a CSV of test metrics to GCS for BigQuery ingestion. | ||
|
|
||
| If the GitHub job failed but produced no test-level `<failure>` records, the | ||
| action synthesises a JUnit failure so infrastructure/setup failures are still | ||
| reported. | ||
|
|
||
| The action is self-contained: it bundles its own helper scripts and does not | ||
| require the calling repository to provide any `scripts/ci` helpers. | ||
|
|
||
| ## Recommended permissions | ||
|
|
||
| The action doesn't require any specific permission. | ||
|
|
||
| ```yaml | ||
| permissions: {} | ||
| ``` | ||
|
|
||
| ## All options | ||
|
|
||
| | Input | Description | Default | | ||
| | ------------------------------ | --------------------------------------------------------------------------------------- | ------------------------------ | | ||
| | [dry-run](#dry-run) | When true, runs junit2jira with `--dry-run` and does not create Jira issues | `false` | | ||
| | [jira-user](#jira-user) | User used to authenticate with Jira | | | ||
| | [jira-token](#jira-token) | Token used to authenticate with Jira | | | ||
| | [jira-url](#jira-url) | Base URL of the Jira instance | `https://redhat.atlassian.net/`| | ||
| | [directory](#directory) | Directory containing the JUnit XML files to scan | | | ||
| | [threshold](#threshold) | Minimal number of failures that results in a single cumulative Jira issue | `5` | | ||
| | [gcp-account](#gcp-account) | Optional GCP service account JSON. When set, the action authenticates gcloud itself | unset | | ||
| | [gcp-project](#gcp-project) | GCP project to set as active when authenticating with gcp-account | `acs-san-stackroxci` | | ||
| | [gcp-metrics](#gcp-metrics) | Whether to upload test metrics to GCS for BigQuery | `true` | | ||
| | [gcs-bucket](#gcs-bucket) | GCS bucket root used to store test metrics | `gs://stackrox-ci-artifacts` | | ||
| | [gcs-subdir](#gcs-subdir) | Subdirectory (relative to the bucket root) used to store test metrics | `test-metrics/upload` | | ||
| | [version](#version) | `junit2jira` release version to download | `v0.0.27` | | ||
|
|
||
| ## Outputs | ||
|
|
||
| | Output | Description | | ||
| | ----------- | -------------------------------------------------- | | ||
| | `new-jiras` | `"true"`/`"false"` — whether new issues were created | | ||
|
|
||
| ### Detailed options | ||
|
|
||
| #### dry-run | ||
|
|
||
| When `true`, `junit2jira` runs with `--dry-run` and no issues are created. | ||
| Commonly wired to only create issues on pushes: | ||
| `${{ github.event_name != 'push' }}`. | ||
|
|
||
| Default value: `false` | ||
|
|
||
| #### jira-user | ||
|
|
||
| User used to authenticate with Jira. Pass via a secret, e.g. | ||
| `${{ secrets.JIRA_USER }}`. | ||
|
|
||
| #### jira-token | ||
|
|
||
| Token used to authenticate with Jira. Pass via a secret, e.g. | ||
| `${{ secrets.JIRA_TOKEN }}`. If empty, the reporting step is skipped so the | ||
| action no-ops gracefully on forks/PRs without secrets. | ||
|
|
||
| #### jira-url | ||
|
|
||
| Base URL of the Jira instance. | ||
|
|
||
| Default value: `https://redhat.atlassian.net/` | ||
|
|
||
| #### directory | ||
|
|
||
| Directory containing the JUnit XML files to scan. `junit2jira` scans it | ||
| recursively for `*.xml` files. | ||
|
|
||
| #### threshold | ||
|
|
||
| Minimal number of failed tests that results in a single cumulative Jira issue | ||
| instead of one issue per failure. | ||
|
|
||
| Default value: `5` | ||
|
|
||
| #### gcp-account | ||
|
|
||
| Optional GCP service account JSON. When provided, the action authenticates with | ||
| gcloud itself (via `google-github-actions/auth`). When omitted, the action | ||
| assumes the caller has already authenticated gcloud. | ||
|
|
||
| Default value: unset | ||
|
|
||
| #### gcp-project | ||
|
|
||
| GCP project to set as active when authenticating with `gcp-account`. | ||
|
|
||
| Default value: `acs-san-stackroxci` | ||
|
|
||
| #### gcp-metrics | ||
|
|
||
| Whether to upload the test metrics CSV to GCS for BigQuery ingestion. Requires | ||
| an authenticated gcloud session (see `gcp-account`). | ||
|
|
||
| Default value: `true` | ||
|
|
||
| #### gcs-bucket | ||
|
|
||
| GCS bucket root used to store test metrics. | ||
|
|
||
| Default value: `gs://stackrox-ci-artifacts` | ||
|
|
||
| #### gcs-subdir | ||
|
|
||
| Subdirectory (relative to the bucket root) used to store test metrics. | ||
|
|
||
| Default value: `test-metrics/upload` | ||
|
|
||
| #### version | ||
|
|
||
| `junit2jira` release version to download. | ||
|
|
||
| Default value: `v0.0.27` | ||
|
|
||
| ## Usage | ||
|
|
||
| The action assumes gcloud is already authenticated (e.g. via | ||
| `google-github-actions/auth`) unless `gcp-account` is provided. | ||
|
|
||
| ```yaml | ||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| # ... run tests, producing JUnit XML under junit-reports/ ... | ||
|
|
||
| - name: Report test failures to Jira | ||
| if: (!cancelled()) | ||
| id: junit2jira | ||
| uses: stackrox/actions/test/junit2jira@main | ||
| with: | ||
| dry-run: ${{ github.event_name != 'push' }} | ||
| jira-user: ${{ secrets.JIRA_USER }} | ||
| jira-token: ${{ secrets.JIRA_TOKEN }} | ||
| directory: junit-reports | ||
| ``` | ||
|
|
||
| To have the action authenticate to GCP itself, pass a service account: | ||
|
|
||
| ```yaml | ||
| - uses: stackrox/actions/test/junit2jira@main | ||
| with: | ||
| jira-user: ${{ secrets.JIRA_USER }} | ||
| jira-token: ${{ secrets.JIRA_TOKEN }} | ||
| directory: junit-reports | ||
| gcp-account: ${{ secrets.GCP_SERVICE_ACCOUNT }} | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| name: junit2jira | ||
| description: Convert JUnit test failures into Jira tickets and upload test metrics | ||
|
|
||
| inputs: | ||
| dry-run: | ||
| description: When true, junit2jira runs with --dry-run and does not create Jira issues. | ||
| required: false | ||
| default: "false" | ||
| jira-user: | ||
| description: User used to authenticate with Jira. | ||
| required: true | ||
| jira-token: | ||
| description: Token used to authenticate with Jira. | ||
| required: true | ||
| jira-url: | ||
| description: Base URL of the Jira instance. | ||
| required: false | ||
| default: https://redhat.atlassian.net/ | ||
| directory: | ||
| description: Directory containing the JUnit XML files to scan. | ||
| required: true | ||
| threshold: | ||
| description: Minimal number of failed tests that will result in a single cumulative Jira issue. | ||
| required: false | ||
| default: "5" | ||
| gcp-account: | ||
| description: | | ||
| Optional GCP service account JSON. When provided, the action authenticates | ||
| with gcloud itself. When omitted, the action assumes the caller has already | ||
| authenticated gcloud (e.g. via google-github-actions/auth). | ||
| required: false | ||
| default: "" | ||
| gcp-project: | ||
| description: GCP project to set as active when authenticating with gcp-account. | ||
| required: false | ||
| default: acs-san-stackroxci | ||
| gcp-metrics: | ||
| description: Whether to upload test metrics to GCS for BigQuery ingestion. | ||
| required: false | ||
| default: "true" | ||
| gcs-bucket: | ||
| description: GCS bucket root used to store test metrics. | ||
| required: false | ||
| default: gs://stackrox-ci-artifacts | ||
| gcs-subdir: | ||
| description: Subdirectory (relative to the bucket root) used to store test metrics. | ||
| required: false | ||
| default: test-metrics/upload | ||
| version: | ||
| description: junit2jira release version to download. | ||
| required: false | ||
| default: v0.0.27 | ||
|
|
||
| outputs: | ||
| new-jiras: | ||
| description: | | ||
| Bool indicating if new Jira issues were created. Explicitly "false" when | ||
| jira-token is empty and Jira reporting was skipped. | ||
| value: ${{ steps.run.outputs.NEW_JIRAS || 'false' }} | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Download junit2jira | ||
| shell: bash | ||
| env: | ||
| VERSION: ${{ inputs.version }} | ||
| run: | | ||
| set -euo pipefail | ||
| BIN_DIR="${RUNNER_TEMP}/junit2jira/${VERSION}" | ||
| BIN_PATH="${BIN_DIR}/junit2jira" | ||
| # Skip downloading release if downloaded already, e.g. when the action is used multiple times. | ||
| if [[ ! -x "$BIN_PATH" ]]; then | ||
| mkdir -p "$BIN_DIR" | ||
| curl --retry 5 --retry-connrefused --silent --show-error --fail --location \ | ||
| --output "$BIN_PATH" "https://github.com/stackrox/junit2jira/releases/download/${VERSION}/junit2jira" | ||
| chmod +x "$BIN_PATH" | ||
| fi | ||
| echo "JUNIT2JIRA_BIN=${BIN_PATH}" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Capture job failure as JUnit if no test failures exist | ||
| shell: bash | ||
| if: always() | ||
| env: | ||
| STEPS_JSON: ${{ toJSON(steps) }} | ||
| ARTIFACT_DIR: ${{ inputs.directory }} | ||
| JOB_NAME: ${{ github.job }} | ||
| JOB_STATUS: ${{ job.status }} | ||
| WORKFLOW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | ||
| run: | | ||
| set -euo pipefail | ||
| "${GITHUB_ACTION_PATH}/../../common/common.sh" \ | ||
| "${GITHUB_ACTION_PATH}/junit2jira.sh" \ | ||
| capture_job_failure_as_junit \ | ||
| "$ARTIFACT_DIR" \ | ||
| "$JOB_NAME" \ | ||
| "$JOB_STATUS" \ | ||
| "$STEPS_JSON" \ | ||
| "$WORKFLOW_RUN_URL" | ||
|
|
||
| - name: Report failures to Jira | ||
| id: run | ||
| shell: bash | ||
| env: | ||
| JIRA_USER: ${{ inputs.jira-user }} | ||
| JIRA_TOKEN: ${{ inputs.jira-token }} | ||
| JIRA_URL: ${{ inputs.jira-url }} | ||
| DIRECTORY: ${{ inputs.directory }} | ||
| THRESHOLD: ${{ inputs.threshold }} | ||
| DRY_RUN: ${{ inputs.dry-run }} | ||
| BASE_LINK: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }} | ||
| BUILD_ID: ${{ github.run_id }} | ||
| BUILD_LINK: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | ||
| BUILD_TAG: ${{ github.ref_name }}@${{ github.sha }} | ||
| JOB_NAME: ${{ github.job }} | ||
| ORCHESTRATOR: ${{ runner.name }} ${{ runner.os }}-${{ runner.arch }} | ||
| if: ${{ env.JIRA_TOKEN != '' }} | ||
| run: | | ||
| set -euo pipefail | ||
| extra_args=() | ||
| if [[ "$DRY_RUN" == "true" ]]; then | ||
| extra_args=(--dry-run) | ||
| else | ||
| echo "Will create Jira issues for JUnit failures found in ${DIRECTORY}" | ||
| fi | ||
| csv_output="$(mktemp --suffix=.csv)" | ||
| summary_file="$(mktemp --suffix=.json)" | ||
| "$JUNIT2JIRA_BIN" \ | ||
| -base-link "$BASE_LINK" \ | ||
| -build-id "$BUILD_ID" \ | ||
| -build-link "$BUILD_LINK" \ | ||
| -build-tag "$BUILD_TAG" \ | ||
| -csv-output "${csv_output}" \ | ||
| -jira-url "$JIRA_URL" \ | ||
| -job-name "$JOB_NAME" \ | ||
| -junit-reports-dir "$DIRECTORY" \ | ||
| -orchestrator "$ORCHESTRATOR" \ | ||
| -threshold "$THRESHOLD" \ | ||
| -summary-output "${summary_file}" \ | ||
| "${extra_args[@]}" | ||
|
|
||
| echo "NEW_JIRAS=$(jq -r '.newJIRAs > 0' "${summary_file}")" >> "$GITHUB_OUTPUT" | ||
| echo "CSV_OUTPUT=${csv_output}" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Authenticate with GCP | ||
| if: inputs.gcp-metrics == 'true' && inputs.gcp-account != '' | ||
| uses: google-github-actions/auth@v2 | ||
| with: | ||
| credentials_json: ${{ inputs.gcp-account }} | ||
| project_id: ${{ inputs.gcp-project }} | ||
|
|
||
| - name: Set up Cloud SDK | ||
| if: inputs.gcp-metrics == 'true' && inputs.gcp-account != '' | ||
| uses: google-github-actions/setup-gcloud@v2 | ||
|
|
||
| - name: Upload test metrics to GCS | ||
| if: inputs.gcp-metrics == 'true' && steps.run.outcome == 'success' | ||
| shell: bash | ||
| env: | ||
| GCS_BUCKET: ${{ inputs.gcs-bucket }} | ||
| GCS_SUBDIR: ${{ inputs.gcs-subdir }} | ||
| run: | | ||
| set -euo pipefail | ||
| "${GITHUB_ACTION_PATH}/../../common/common.sh" \ | ||
| "${GITHUB_ACTION_PATH}/junit2jira.sh" \ | ||
| save_test_metrics \ | ||
| "$CSV_OUTPUT" \ | ||
| "$GCS_BUCKET" \ | ||
| "$GCS_SUBDIR" | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.