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
56 changes: 40 additions & 16 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
name: Release

on:
release:
types:
- published
workflow_dispatch:
inputs:
tag_name:
description: "Release tag (format: {major}.{minor}.{patch}.{build}_{scanner_major}.{scanner_minor}.{scanner_patch})"
required: true
type: string

jobs:
release:
Expand All @@ -26,27 +29,41 @@ jobs:
development/kv/data/slack webhook | slack_webhook;
- name: Get the version
id: get_version
shell: bash
env:
TAG_NAME: ${{ inputs.tag_name }}
run: |
full_image_tag=${{ github.event.release.tag_name }}
if [[ ! ${full_image_tag} =~ ^[1-9][0-9]+.[0-9]+.[0-9]+.[0-9]+_[0-9]+.[0-9]+.[0-9]+ ]]; then
full_image_tag=$TAG_NAME
if [[ ! ${full_image_tag} =~ ^[1-9][0-9]*\.[0-9]+\.[0-9]+\.[0-9]+_[0-9]+\.[0-9]+\.[0-9]+ ]]; then
echo "The release tag should be in the format of {major}.{minor}.{patch}.{buildnumber}_{scanner_major}.{scanner_minor}.{scanner_patch} but it was ${full_image_tag}"
exit 1
fi

IFS=. read docker_major docker_minor docker_patch build_and_scanner <<<"${full_image_tag}"
IFS=_ read buildnumber scanner_version <<<"${build_and_scanner}"
echo "major_version=${docker_major}" >> $GITHUB_OUTPUT
echo "major_minor=${docker_major}.${docker_minor}" >> $GITHUB_OUTPUT
echo "full_image_tag=${full_image_tag}" >> $GITHUB_OUTPUT
echo "buildnumber=${buildnumber}" >> $GITHUB_OUTPUT
shell: bash
- uses: actions/checkout@v2
with:
ref: ${{ github.event.release.tag_name }}
Comment thread
julien-carsique-sonarsource marked this conversation as resolved.
- uses: actions/checkout@v2
- uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2
- uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2
with:
repository: SonarSource/sonar-scanning-examples
path: target_repository
- name: Create and push release tag
env:
TAG_NAME: ${{ inputs.tag_name }}
run: |
if git ls-remote --exit-code --tags origin "$TAG_NAME" > /dev/null 2>&1; then
echo "Tag '$TAG_NAME' already exists on origin. To retry, clean up the partial release first:"
echo " 1. Delete the tag: git push origin :refs/tags/$TAG_NAME"
echo " 2. If a draft GitHub release exists for '$TAG_NAME', delete it before re-dispatching."
exit 1
Comment thread
sonar-review-alpha[bot] marked this conversation as resolved.
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "$TAG_NAME" -m "Release $TAG_NAME"
git push origin "$TAG_NAME"
Comment thread
sonar-review-alpha[bot] marked this conversation as resolved.
- name: Pull staged image
run: |
docker login repox-sonarsource-docker-builds.jfrog.io --username ${{ fromJSON(steps.secrets.outputs.vault).repox_username }} --password-stdin <<< "${{ fromJSON(steps.secrets.outputs.vault).repox_access_token }}"
Expand All @@ -58,21 +75,23 @@ jobs:
filename: "sonar-scanner-cli-docker-${{ steps.get_version.outputs.full_image_tag }}-bom.json"
upload-artifact: true
upload-release-assets: true
release-tag: ${{ inputs.tag_name }}
env:
GPG_PRIVATE_KEY_PASSPHRASE: ${{ fromJSON(steps.secrets.outputs.vault).gpg_passphrase }}
GPG_PRIVATE_KEY_BASE64: ${{ fromJSON(steps.secrets.outputs.vault).gpg_key }}
- name: Promote the staged build
env:
ARTIFACTORY_URL: https://repox.jfrog.io/repox
TAG_NAME: ${{ inputs.tag_name }}
run: |
source_repo_key=sonarsource-docker-builds
target_repo_key=sonarsource-docker-releases
docker_image=sonarsource/sonar-scanner-cli
buildnumber=${{ steps.get_version.outputs.buildnumber }}
full_image_tag=${{ github.event.release.tag_name }}
full_image_tag=$TAG_NAME
DATA_JSON="{ \"targetRepo\": \"${target_repo_key}\", \"dockerRepository\": \"${docker_image}\", \"tag\": \"${buildnumber}\", \"targetTag\": \"${full_image_tag}\", \"copy\": true }"
HTTP_CODE=$(curl -s -o /dev/null -w %{http_code} -H "Content-Type: application/json" -H "Authorization: Bearer ${{ fromJSON(steps.secrets.outputs.vault).repox_access_token }}" -X POST "$ARTIFACTORY_URL/api/docker/$source_repo_key/v2/promote" --data "$DATA_JSON")
if [ "$HTTP_CODE" != "200" ]; then
if [[ "$HTTP_CODE" != "200" ]]; then
echo "Cannot promote ${docker_image}#${full_image_tag}: ($HTTP_CODE)"
exit 1
else
Expand All @@ -81,7 +100,7 @@ jobs:
- name: Push image to Docker Hub
run: |
buildnumber=${{ steps.get_version.outputs.buildnumber }}

docker tag "repox-sonarsource-docker-builds.jfrog.io/sonarsource/sonar-scanner-cli:${buildnumber}" "sonarsource/sonar-scanner-cli:latest"
docker tag "repox-sonarsource-docker-builds.jfrog.io/sonarsource/sonar-scanner-cli:${buildnumber}" "sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_version }}"
docker tag "repox-sonarsource-docker-builds.jfrog.io/sonarsource/sonar-scanner-cli:${buildnumber}" "sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_minor }}"
Expand All @@ -93,6 +112,11 @@ jobs:
docker push sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_version }}
docker push sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.major_minor }}
docker push sonarsource/sonar-scanner-cli:${{ steps.get_version.outputs.full_image_tag }}
- name: Publish release
env:
GH_TOKEN: ${{ github.token }}
Comment thread
sonar-review-alpha[bot] marked this conversation as resolved.
TAG_NAME: ${{ inputs.tag_name }}
run: gh release edit "$TAG_NAME" --draft=false
- name: Notify success on Slack
uses: slackapi/slack-github-action@v2.0.0
with:
Expand All @@ -104,7 +128,7 @@ jobs:
"attachments": [
{
"color": "#00ff00",
"text": "Release `${{ github.event.release.tag_name }}` successful for `${{ github.repository }}` by `${{ github.actor }}`.\n <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Link to workflow run>"
"text": "Release `${{ inputs.tag_name }}` successful for `${{ github.repository }}` by `${{ github.actor }}`.\n <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Link to workflow run>"
}
]
}
Expand All @@ -120,7 +144,7 @@ jobs:
"attachments": [
{
"color": "#ff0000",
"text": "Release `${{ github.event.release.tag_name }}` failed for `${{ github.repository }}` by `${{ github.actor }}`.\n <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Link to workflow run>"
"text": "Release `${{ inputs.tag_name }}` failed for `${{ github.repository }}` by `${{ github.actor }}`.\n <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Link to workflow run>"
}
]
}
26 changes: 26 additions & 0 deletions DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,29 @@ The QA process is handled on `.cirrus.yml`, which is responsible for the followi
- build the image
- test the image by running a scan on a sample project
- run scans to find potential vulnerabilities

## Releasing

Releases are triggered manually through the `Release` workflow (`.github/workflows/release.yml`).

### How to release

1. Go to the [Release workflow](../../actions/workflows/release.yml) on GitHub Actions.
2. Click **Run workflow** and select the branch to release from (see [Branch to dispatch from](#branch-to-dispatch-from) below).
3. Provide the `tag_name` input in the format `{major}.{minor}.{patch}.{build}_{scanner_major}.{scanner_minor}.{scanner_patch}` (e.g. `4.8.0.2699_6.2.1`).

The workflow validates the tag format, creates and pushes the git tag at HEAD of the dispatched branch, generates the SBOM, promotes the staged Docker image, pushes it to Docker Hub, and finally publishes the GitHub release.

### Branch to dispatch from

The git tag is created at HEAD of the branch the workflow is dispatched from. Choose the branch accordingly:

- **Latest release**: dispatch from `master`.
- **Maintenance release on a long-lived branch** (e.g. `branch-4.8`): dispatch from that `branch-*` branch, **not** from `master`. Dispatching from `master` would tag a commit that does not belong to the maintenance line.

### Recovering from a failed release

If the workflow fails after the git tag has been pushed, re-dispatching with the same tag will fail at the pre-flight check. To recover:

1. Delete the tag from the remote: `git push origin :refs/tags/<TAG_NAME>`
2. If a draft GitHub release was created for that tag, delete it from the [Releases page](../../releases) before re-dispatching.
Loading