Skip to content
Closed
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
120 changes: 120 additions & 0 deletions run-iris/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Run IRIS Analysis Action

A reusable GitHub composite action that runs SonarSource IRIS analysis tool to synchronize projects between SonarQube instances.

## Usage

### External Repository Usage

When using this action from another repository (e.g., if moved to a dedicated action repository):

```yaml
- name: Run IRIS Analysis
uses: SonarSource/sonar-iris-action/.github/actions/run-iris@main
with:
source_project_key: "SonarSource_your-project-name"
source_organization: "sonarsource"
destination_project_key: "SonarSource_your-project-name"
destination_organization: "sonarsource"
```

### Basic Usage

```yaml
jobs:
run-iris:
runs-on: sonar-runner-on-demand
permissions:
id-token: write
contents: read
steps:
- name: Run IRIS Analysis
uses: ./.github/actions/run-iris
with:
source_project_key: "SonarSource_your-project-name"
source_organization: "your-organization"
destination_project_key: "SonarSource_your-project-name"
destination_organization: "your-organization"
```

### Complete Workflow Example

```yaml
name: Run IRIS Analysis

permissions:
id-token: write
contents: read
pull-requests: read
statuses: read
checks: read

on:
schedule:
- cron: '20 */12 * * *'
workflow_dispatch:
inputs:
github_environment:
description: 'GitHub Environment'
required: false
type: string
default: "ManualDispatch"
runner_label:
description: 'GitHub Action runner'
required: false
type: string
default: "ubuntu-latest"

jobs:
run-iris:
runs-on: ${{ github.event_name == 'workflow_dispatch' && inputs.runner_label || 'ubuntu-latest' }}
steps:
- name: Run IRIS Analysis
uses: ./.github/actions/run-iris
with:
source_project_key: "SonarSource_your-project-name"
source_organization: "your-organization"
destination_project_key: "SonarSource_your-project-name"
destination_organization: "your-organization"
github_environment: ${{ github.event_name == 'workflow_dispatch' && inputs.github_environment || 'Scheduled' }}
```

## Inputs

### Required Inputs

| Input | Description | Required | Default |
|-------|-------------|----------|---------|
| `source_project_key` | Source project key | Yes | - |
| `source_organization` | Source organization name | Yes | - |
| `destination_project_key` | Destination project key | Yes | - |
| `destination_organization` | Destination organization name | Yes | - |

### Optional Inputs

| Input | Description | Required | Default |
|-------|-------------|----------|---------|
| `github_environment` | GitHub Environment | No | `ManualDispatch` |
| `sonar_sqc_eu_url` | SonarCloud EU URL | No | `https://sonarcloud.io` |
| `sonar_sqc_us_url` | SonarCloud US URL | No | `https://sonarqube.us` |
| `sonar_next_url` | SonarQube Next URL | No | `https://next.sonarqube.com/sonarqube` |

## Prerequisites

### Required Permissions

The workflow using this action must have the following permissions:

```yaml
permissions:
id-token: write # Required for vault authentication
contents: read # Required for checkout
```

### Required Secrets

This action requires access to SonarSource vault with the following secrets:

- `development/kv/data/iris` - IRIS tokens for different instances
- `development/artifactory/token/{REPO_OWNER_NAME_DASH}-private-reader` - Artifactory credentials
- `development/kv/data/repox` - Artifactory URL
105 changes: 105 additions & 0 deletions run-iris/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Run IRIS Analysis
description: Runs SonarSource IRIS analysis tool to synchronize projects between SonarQube instances

inputs:
github_environment:
description: GitHub Environment
required: false
default: ManualDispatch
source_project_key:
description: Source project key
required: true
source_organization:
description: Source organization name
required: true
destination_project_key:
description: Destination project key
required: true
destination_organization:
description: Destination organization name
required: true
sonar_sqc_eu_url:
description: SonarCloud EU URL
required: false
default: https://sonarcloud.io
sonar_sqc_us_url:
description: SonarCloud US URL
required: false
default: https://sonarqube.us
sonar_next_url:
description: SonarQube Next URL
required: false
default: https://next.sonarqube.com/sonarqube

runs:
using: composite
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
fetch-depth: 1 # Having a shallow clone here reduces overhead significantly
fetch-tags: false

- name: Mise setup
id: mise-setup
uses: jdx/mise-action@13abe502c30c1559a5c37dff303831bab82c9402 # v2.2.3
with:
cache_save: true
cache_key_prefix: mise-v1
mise_toml: |
[tools]
poetry = '1.8.5'
python = '3.13'
pipenv = '2024.4.0'
sops = '3.9.0'
"npm:aws-cdk" = "v2"
"npm:newman" = "latest"
java = ['corretto-21', 'corretto-17']
env:
GITHUB_TOKEN: ${{ github.token }}

- name: Print versions
shell: bash
run: |
echo "NPM: $(npm -v)"
echo "Python: $(python3 --version)"
echo "Pip: $(pip --version)"
echo "Pipenv: $(pipenv --version)"
echo "Poetry: $(poetry --version)"
echo "Node: $(node --version)"
echo "CDK: $(cdk --version)"
echo "Newman: $(newman --version)"
echo "Default Java: $(java --version)"
echo "All Java distributions installed: $(env | grep JAVA_)"

- name: Get secrets from Vault
id: secrets
uses: SonarSource/vault-action-wrapper@eeb41b89722805725f07028c393860a50c60b51d
with:
secrets: |
development/kv/data/iris next | SONAR_IRIS_NEXT_TOKEN;
development/kv/data/iris sqc-eu | SONAR_IRIS_SQC_EU_TOKEN;
development/kv/data/iris sqc-us | SONAR_IRIS_SQC_US_TOKEN;
development/artifactory/token/{REPO_OWNER_NAME_DASH}-private-reader username | ARTIFACTORY_USERNAME;
development/artifactory/token/{REPO_OWNER_NAME_DASH}-private-reader access_token | ARTIFACTORY_ACCESS_TOKEN;
development/kv/data/repox artifactory_url | ARTIFACTORY_URL;

- name: Run IRIS
shell: bash
run: |
chmod +x ${{ github.action_path }}/run_iris.sh
${{ github.action_path }}/run_iris.sh
env:
SOURCE_PROJECT_KEY: ${{ inputs.source_project_key }}
SOURCE_ORGANIZATION: ${{ inputs.source_organization }}
DESTINATION_PROJECT_KEY: ${{ inputs.destination_project_key }}
DESTINATION_ORGANIZATION: ${{ inputs.destination_organization }}
SONAR_SQC_EU_URL: ${{ inputs.sonar_sqc_eu_url }}
SONAR_IRIS_SQC_EU_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).SONAR_IRIS_SQC_EU_TOKEN }}
SONAR_SQC_US_URL: ${{ inputs.sonar_sqc_us_url }}
SONAR_IRIS_SQC_US_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).SONAR_IRIS_SQC_US_TOKEN }}
SONAR_NEXT_URL: ${{ inputs.sonar_next_url }}
SONAR_IRIS_NEXT_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).SONAR_IRIS_NEXT_TOKEN }}
ARTIFACTORY_USERNAME: ${{ fromJSON(steps.secrets.outputs.vault).ARTIFACTORY_USERNAME }}
ARTIFACTORY_ACCESS_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).ARTIFACTORY_ACCESS_TOKEN }}
ARTIFACTORY_URL: ${{ fromJSON(steps.secrets.outputs.vault).ARTIFACTORY_URL }}
77 changes: 77 additions & 0 deletions run-iris/run_iris.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/bin/bash
set -euo pipefail

: "${ARTIFACTORY_USERNAME?}" "${ARTIFACTORY_ACCESS_TOKEN?}" "${ARTIFACTORY_URL?}"
: "${SONAR_SQC_EU_URL?}" "${SONAR_IRIS_SQC_EU_TOKEN?}"
: "${SONAR_SQC_US_URL?}" "${SONAR_IRIS_SQC_US_TOKEN?}"
: "${SONAR_NEXT_URL?}" "${SONAR_IRIS_NEXT_TOKEN?}"
: "${SOURCE_PROJECT_KEY?}" "${SOURCE_ORGANIZATION?}"
: "${DESTINATION_PROJECT_KEY?}" "${DESTINATION_ORGANIZATION?}"

# Run IRIS from SQC EU to SQS
function run_iris_next () {
java \
-Diris.source.projectKey="$SOURCE_PROJECT_KEY" \
-Diris.source.organization="$SOURCE_ORGANIZATION" \
-Diris.source.url="$SONAR_SQC_EU_URL" \
-Diris.source.token="$SONAR_IRIS_SQC_EU_TOKEN" \
-Diris.destination.projectKey="$DESTINATION_PROJECT_KEY" \
-Diris.destination.url="$SONAR_NEXT_URL" \
-Diris.destination.token="$SONAR_IRIS_NEXT_TOKEN" \
-Diris.dryrun="$1" \
-jar iris-\[RELEASE\]-jar-with-dependencies.jar
}

# Run IRIS from SQC EU to SQC US
function run_iris_sqc_us () {
java \
-Diris.source.projectKey="$SOURCE_PROJECT_KEY" \
-Diris.source.organization="$SOURCE_ORGANIZATION" \
-Diris.source.url="$SONAR_SQC_EU_URL" \
-Diris.source.token="$SONAR_IRIS_SQC_EU_TOKEN" \
-Diris.destination.projectKey="$DESTINATION_PROJECT_KEY" \
-Diris.destination.organization="$DESTINATION_ORGANIZATION" \
-Diris.destination.url="$SONAR_SQC_US_URL" \
-Diris.destination.token="$SONAR_IRIS_SQC_US_TOKEN" \
-Diris.dryrun="$1" \
-jar iris-\[RELEASE\]-jar-with-dependencies.jar
}

VERSION="\[RELEASE\]"
HTTP_CODE=$(\
curl \
--write-out '%{http_code}' \
--location \
--remote-name \
--user "$ARTIFACTORY_USERNAME:$ARTIFACTORY_ACCESS_TOKEN" \
"$ARTIFACTORY_URL/sonarsource-private-releases/com/sonarsource/iris/iris/$VERSION/iris-$VERSION-jar-with-dependencies.jar"\
)

if [ "$HTTP_CODE" != "200" ]; then
echo "Download $VERSION failed -> $HTTP_CODE"
exit 1
else
echo "Downloaded $VERSION"
fi

echo "===== Execute IRIS Next as dry-run"
run_iris_next "true"
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "===== Failed to run IRIS dry-run"
exit 1
else
echo "===== Successful IRIS Next dry-run - executing IRIS for real."
run_iris_next "false"
fi

echo "===== Execute IRIS SQC US as dry-run"
run_iris_sqc_us "true"
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "===== Failed to run IRIS dry-run"
exit 1
else
echo "===== Successful IRIS SQC US dry-run - executing IRIS for real."
run_iris_sqc_us "false"
fi