Repository navigation
BUILD-13269: Add renovate action #372
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,6 +61,7 @@ These badges show the status of workflows in dummy repositories that use (or sho | |
| - [`config-uv`](#config-uv) | ||
| - [`config-bun`](#config-bun) | ||
| - [`config-nuget`](#config-nuget) | ||
| - [`renovate`](#renovate) | ||
| - [`promote`](#promote) | ||
| - [`pr_cleanup`](#pr_cleanup) | ||
| - [`code-signing`](#code-signing) | ||
|
|
@@ -1612,6 +1613,96 @@ steps: | |
|
|
||
| --- | ||
|
|
||
| ## `renovate` | ||
|
|
||
| Run self-hosted [Renovate](https://docs.renovatebot.com/) on the current repository. | ||
|
|
||
| Use it instead of the Mend-hosted Renovate app when lockfiles pin the production JFrog Edge: Mend can't reach the Edge, so the | ||
| lockfile updates it makes fail or write SaaS URLs back. Run it on a self-hosted runner, and disable the Mend app for the | ||
| repository so the two don't open competing pull requests. | ||
|
|
||
| The action installs the `renovate` npm package from the selected Repox and runs it on Node.js installed with mise. It passes | ||
| the selected Repox reader to the commands Renovate runs (lockfile updates and `postUpgradeTasks`). Package lookups follow the | ||
| repository's Renovate configuration; the shared `SonarSource/renovate-config` presets use SaaS Repox with the `REPOX_TOKEN` | ||
| secret, which the action sets. | ||
|
|
||
| Renovate runs with `binarySource: global`, so the tools needed for lockfile updates must be on `PATH`. The action runs `mise`, | ||
| which installs the tools declared in the repository's mise configuration. | ||
|
|
||
| ### Requirements | ||
|
|
||
| #### Required GitHub Permissions | ||
|
|
||
| - `id-token: write` | ||
|
|
||
| The other permissions come from the GitHub token used by Renovate. | ||
|
|
||
| #### Required Vault Permissions | ||
|
|
||
| - `renovate`: GitHub App token for the repository, unless `github-token` is set. It needs `checks`, `contents`, `issues`, | ||
| `pull_requests`, `statuses` and `workflows` write access, and `metadata` read access. | ||
| - `public-reader` or `private-reader`: Artifactory role for reading dependencies, for both SaaS Repox and the selected Repox | ||
|
|
||
| #### Other Dependencies | ||
|
|
||
| The tools used by the repository's lockfile updates and `postUpgradeTasks`, declared in its mise configuration. | ||
|
|
||
| ### Usage | ||
|
|
||
| ```yaml | ||
| on: | ||
| workflow_dispatch: | ||
| schedule: | ||
| - cron: "0 21 * * 1-5" | ||
|
|
||
| jobs: | ||
| renovate: | ||
| runs-on: sonar-xs | ||
| permissions: | ||
| id-token: write | ||
| steps: | ||
| - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | ||
| - uses: SonarSource/ci-github-actions/renovate@v2 | ||
| env: | ||
| RENOVATE_ALLOWED_COMMANDS: '["^bun install$"]' | ||
| ``` | ||
|
|
||
| Global-only Renovate options, such as `allowedCommands` or `force`, can't be set in the repository's Renovate configuration. Set | ||
| them as `RENOVATE_*` environment variables on the step, as above. | ||
|
|
||
| ### Inputs | ||
|
|
||
| | Input | Description | Default | | ||
| |---------------------------|-------------------------------------------------------|----------------------------------------------------------------------| | ||
| | `renovate-version` | Version of the `renovate` npm package to run | `43.257.5` | | ||
| | `node-version` | Node.js version used to run Renovate | `24.11.0` | | ||
| | `github-token` | GitHub token used by Renovate | The repository's `renovate` GitHub App token from Vault | | ||
| | `artifactory-reader-role` | Suffix for the Artifactory reader role in Vault | `private-reader` for private repos, `public-reader` for public repos | | ||
| | `repox-url` | URL for Repox | Runner-dependent (see Edge section) | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Quality: Edge section still scopes runner-based Repox selection to config-/build-The Was this helpful? React with 👍 / 👎 |
||
|
|
||
| Pull requests opened with `GITHUB_TOKEN` don't trigger workflows, so CI doesn't run on them. | ||
|
|
||
| ### Input Environment Variables | ||
|
|
||
| | Environment Variable | Description | | ||
| |---------------------------------|------------------------------------------------------------------------------------------------| | ||
| | `RENOVATE_*`, `LOG_LEVEL` | Passed to Renovate | | ||
| | `RENOVATE_REPOSITORIES` | Repositories to process. Defaults to the current repository | | ||
| | `RENOVATE_SECRETS` | JSON object merged with the `REPOX_TOKEN` secret set by the action | | ||
| | `RENOVATE_CUSTOM_ENV_VARIABLES` | JSON object merged with the variables the action sets for Renovate commands | | ||
|
|
||
| ### Environment Variables for Renovate Commands | ||
|
|
||
| | Environment Variable | Description | | ||
| |----------------------------|------------------------------------------------| | ||
| | `ARTIFACTORY_URL` | Selected Repox Artifactory URL | | ||
| | `ARTIFACTORY_USERNAME` | Selected Repox reader username | | ||
| | `ARTIFACTORY_ACCESS_TOKEN` | Selected Repox reader access token | | ||
| | `BUN_CONFIG_REGISTRY` | npm registry URL under the selected Repox | | ||
| | `BUN_CONFIG_TOKEN` | Selected Repox reader access token | | ||
|
|
||
| --- | ||
|
|
||
| ## `promote` | ||
|
|
||
| This action promotes a build in JFrog Artifactory and updates the GitHub status check accordingly. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| --- | ||
| name: Renovate | ||
| description: GitHub Action to run self-hosted Renovate on the current repository, installed from Repox and resolving lockfile updates | ||
| through the selected Repox | ||
| inputs: | ||
| renovate-version: | ||
| description: Version of the `renovate` npm package to run | ||
| default: 43.257.5 | ||
| node-version: | ||
| description: Node.js version used to run Renovate, installed with mise | ||
| default: 24.11.0 | ||
| github-token: | ||
| description: GitHub token used by Renovate. Defaults to the repository's `renovate` GitHub App token from Vault. | ||
| default: '' | ||
| artifactory-reader-role: | ||
| description: Suffix for the Artifactory reader role in Vault. Defaults to `private-reader` for private repositories, and `public-reader` | ||
| for public repositories. | ||
| default: '' | ||
| repox-url: | ||
| description: URL for Repox used to install Renovate and by the commands Renovate runs. Defaults to SaaS on GitHub-hosted runners and | ||
| the production Edge on self-hosted runners. Explicit URLs override runner selection. | ||
| default: ${{ runner.environment == 'github-hosted' && 'https://repox.jfrog.io' || 'https://repox-internal.sonar.build' }} | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Set local action paths | ||
| shell: bash | ||
| env: | ||
| ARTIFACTORY_READER_ROLE: ${{ inputs.artifactory-reader-role != '' && inputs.artifactory-reader-role || | ||
| (github.event.repository.visibility == 'public' && 'public-reader' || 'private-reader') }} | ||
| run: | | ||
| echo "ACTION_PATH_RENOVATE=${{ github.action_path }}" >> "$GITHUB_ENV" | ||
| echo "ARTIFACTORY_READER_ROLE=${ARTIFACTORY_READER_ROLE}" >> "$GITHUB_ENV" | ||
|
|
||
| - uses: step-security/mise-action@a225bbd7c202ddf57dd76dff22bb7992f6314173 # v5.1.2 | ||
| with: | ||
| version: 2026.10.17 | ||
|
|
||
| - uses: SonarSource/vault-action-wrapper@a7fa5fd4a4e4e0f2593f6137c0812cac196cf4ce # 3.7.0 | ||
| id: secrets | ||
| with: | ||
| # yamllint disable rule:line-length | ||
| url: ${{ contains(inputs.repox-url, '.dev.sonar.build') && 'https://vault.dev.sonar.build' || 'https://vault.sonar.build' }} | ||
| secrets: | | ||
| ${{ inputs.github-token == '' && 'development/github/token/{REPO_OWNER_NAME_DASH}-renovate token | RENOVATE_TOKEN;' || '' }} | ||
| development/artifactory/token/{REPO_OWNER_NAME_DASH}-${{ env.ARTIFACTORY_READER_ROLE }} access_token | REPOX_TOKEN; | ||
| development/${{ contains(inputs.repox-url, 'jfrog.io') && 'artifactory' || (contains(inputs.repox-url, '.dev.sonar.build') && 'artifactory-edge-dev' || 'artifactory-edge-prod') }}/token/{REPO_OWNER_NAME_DASH}-${{ env.ARTIFACTORY_READER_ROLE }} username | ARTIFACTORY_USERNAME; | ||
| development/${{ contains(inputs.repox-url, 'jfrog.io') && 'artifactory' || (contains(inputs.repox-url, '.dev.sonar.build') && 'artifactory-edge-dev' || 'artifactory-edge-prod') }}/token/{REPO_OWNER_NAME_DASH}-${{ env.ARTIFACTORY_READER_ROLE }} access_token | ARTIFACTORY_ACCESS_TOKEN; | ||
| # yamllint enable rule:line-length | ||
|
|
||
| - name: Run Renovate | ||
| shell: bash | ||
| env: | ||
| RENOVATE_VERSION: ${{ inputs.renovate-version }} | ||
| NODE_VERSION: ${{ inputs.node-version }} | ||
| ARTIFACTORY_URL: ${{ format('{0}/artifactory', inputs.repox-url) }} | ||
| ARTIFACTORY_USERNAME: ${{ fromJSON(steps.secrets.outputs.vault).ARTIFACTORY_USERNAME }} | ||
| ARTIFACTORY_ACCESS_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).ARTIFACTORY_ACCESS_TOKEN }} | ||
| REPOX_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).REPOX_TOKEN }} | ||
| RENOVATE_TOKEN: ${{ inputs.github-token != '' && inputs.github-token || fromJSON(steps.secrets.outputs.vault).RENOVATE_TOKEN }} | ||
| run: $ACTION_PATH_RENOVATE/renovate.sh |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| #!/bin/bash | ||
| # Run self-hosted Renovate on the current repository. | ||
| # | ||
| # Renovate is installed with npm from the selected Repox, and the commands it runs (lockfile updates, post-upgrade tasks) | ||
| # get the selected Repox reader through customEnvVariables. | ||
| # | ||
| # Required environment variables (must be explicitly provided): | ||
| # - RENOVATE_VERSION: Version of the renovate npm package | ||
| # - NODE_VERSION: Node.js version used to run Renovate | ||
| # - ARTIFACTORY_URL: URL to the selected Artifactory | ||
| # - ARTIFACTORY_USERNAME: Reader username for the selected Artifactory | ||
| # - ARTIFACTORY_ACCESS_TOKEN: Reader access token for the selected Artifactory | ||
| # - REPOX_TOKEN: SaaS Repox reader access token, exposed as the REPOX_TOKEN Renovate secret | ||
| # - RENOVATE_TOKEN: GitHub token used by Renovate | ||
| # | ||
| # Optional environment variables: | ||
| # - RENOVATE_SECRETS, RENOVATE_CUSTOM_ENV_VARIABLES: JSON objects merged with the values set by this script | ||
| # - Any other RENOVATE_* variable or LOG_LEVEL is passed to Renovate unchanged | ||
| # | ||
| # GitHub Actions auto-provided: | ||
| # - GITHUB_REPOSITORY: Repository processed when RENOVATE_REPOSITORIES is not set | ||
| # - RUNNER_TEMP: Directory where Renovate is installed | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| : "${RENOVATE_VERSION:?}" "${NODE_VERSION:?}" "${ARTIFACTORY_URL:?}" "${ARTIFACTORY_USERNAME:?}" "${ARTIFACTORY_ACCESS_TOKEN:?}" | ||
| : "${REPOX_TOKEN:?}" "${RENOVATE_TOKEN:?}" "${GITHUB_REPOSITORY:?}" "${RUNNER_TEMP:?}" | ||
|
|
||
| install_renovate() { | ||
| local registry="${ARTIFACTORY_URL}/api/npm/npm/" | ||
| RENOVATE_PREFIX="$RUNNER_TEMP/renovate" | ||
| NPM_CONFIG_USERCONFIG="$RUNNER_TEMP/renovate.npmrc" | ||
| export NPM_CONFIG_USERCONFIG | ||
| { | ||
| echo "registry=$registry" | ||
| echo "//${registry#https://}:_authToken=$ARTIFACTORY_ACCESS_TOKEN" | ||
| } > "$NPM_CONFIG_USERCONFIG" | ||
| echo "Installing renovate@$RENOVATE_VERSION from $registry" | ||
| mise exec "node@$NODE_VERSION" -- npm install --prefix "$RENOVATE_PREFIX" --no-audit --no-fund "renovate@$RENOVATE_VERSION" | ||
| return 0 | ||
| } | ||
|
|
||
| export_renovate_config() { | ||
| local registry="${ARTIFACTORY_URL}/api/npm/npm/" | ||
| export RENOVATE_REPOSITORIES="${RENOVATE_REPOSITORIES:-$GITHUB_REPOSITORY}" | ||
| export RENOVATE_ONBOARDING="${RENOVATE_ONBOARDING:-false}" | ||
| export RENOVATE_BINARY_SOURCE="${RENOVATE_BINARY_SOURCE:-global}" | ||
| RENOVATE_SECRETS=$(jq -cn --arg token "$REPOX_TOKEN" --argjson extra "${RENOVATE_SECRETS:-"{}"}" \ | ||
| '{REPOX_TOKEN: $token} + $extra') | ||
| RENOVATE_CUSTOM_ENV_VARIABLES=$(jq -cn --arg url "$ARTIFACTORY_URL" --arg registry "$registry" \ | ||
| --arg username "$ARTIFACTORY_USERNAME" --arg token "$ARTIFACTORY_ACCESS_TOKEN" \ | ||
| --argjson extra "${RENOVATE_CUSTOM_ENV_VARIABLES:-"{}"}" \ | ||
| '{ARTIFACTORY_URL: $url, ARTIFACTORY_USERNAME: $username, ARTIFACTORY_ACCESS_TOKEN: $token, | ||
| BUN_CONFIG_REGISTRY: $registry, BUN_CONFIG_TOKEN: $token} + $extra') | ||
| export RENOVATE_SECRETS RENOVATE_CUSTOM_ENV_VARIABLES | ||
| echo "Renovate repositories: $RENOVATE_REPOSITORIES" | ||
| echo "Dependency registry for Renovate commands: $registry" | ||
| return 0 | ||
| } | ||
|
|
||
| main() { | ||
| echo "::group::Install Renovate" | ||
| install_renovate | ||
| echo "::endgroup::" | ||
| export_renovate_config | ||
| mise exec "node@$NODE_VERSION" -- "$RENOVATE_PREFIX/node_modules/.bin/renovate" | ||
| return 0 | ||
| } | ||
|
|
||
| if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then | ||
| main | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| #!/usr/bin/env bash | ||
| eval "$(shellspec - -c) exit 1" | ||
|
|
||
| Mock mise | ||
| echo "mise $*" | ||
| End | ||
|
|
||
| export RENOVATE_VERSION="43.257.5" | ||
| export NODE_VERSION="24.11.0" | ||
| export ARTIFACTORY_URL="https://repox-internal.sonar.build/artifactory" | ||
| export ARTIFACTORY_USERNAME="test-user" | ||
| export ARTIFACTORY_ACCESS_TOKEN="edge-token" | ||
| export REPOX_TOKEN="saas-token" | ||
| export RENOVATE_TOKEN="github-token" | ||
| export GITHUB_REPOSITORY="my-org/my-repo" | ||
| RUNNER_TEMP=$(mktemp -d) | ||
| export RUNNER_TEMP | ||
|
|
||
| EDGE_REGISTRY="https://repox-internal.sonar.build/artifactory/api/npm/npm/" | ||
|
|
||
| Describe 'renovate/renovate.sh' | ||
| It 'does not run main when sourced' | ||
| When run source renovate/renovate.sh | ||
| The status should be success | ||
| The lines of output should equal 0 | ||
| The lines of error should equal 0 | ||
| End | ||
| End | ||
|
|
||
| Include renovate/renovate.sh | ||
|
|
||
| Describe 'install_renovate()' | ||
| It 'installs the pinned Renovate version from the selected Repox' | ||
| When call install_renovate | ||
| The status should be success | ||
| The line 1 should equal "Installing renovate@43.257.5 from $EDGE_REGISTRY" | ||
| The line 2 should equal \ | ||
| "mise exec node@24.11.0 -- npm install --prefix $RUNNER_TEMP/renovate --no-audit --no-fund renovate@43.257.5" | ||
| The contents of file "$RUNNER_TEMP/renovate.npmrc" should include "registry=$EDGE_REGISTRY" | ||
| The contents of file "$RUNNER_TEMP/renovate.npmrc" should include \ | ||
| "//repox-internal.sonar.build/artifactory/api/npm/npm/:_authToken=edge-token" | ||
| End | ||
| End | ||
|
|
||
| Describe 'export_renovate_config()' | ||
| It 'sets the defaults, the REPOX_TOKEN secret and the reader for Renovate commands' | ||
| When call export_renovate_config | ||
| The status should be success | ||
| The line 1 should equal "Renovate repositories: my-org/my-repo" | ||
| The line 2 should equal "Dependency registry for Renovate commands: $EDGE_REGISTRY" | ||
| The variable RENOVATE_REPOSITORIES should equal "my-org/my-repo" | ||
| The variable RENOVATE_ONBOARDING should equal "false" | ||
| The variable RENOVATE_BINARY_SOURCE should equal "global" | ||
| The variable RENOVATE_SECRETS should equal '{"REPOX_TOKEN":"saas-token"}' | ||
| The variable RENOVATE_CUSTOM_ENV_VARIABLES should include "\"BUN_CONFIG_REGISTRY\":\"$EDGE_REGISTRY\"" | ||
| The variable RENOVATE_CUSTOM_ENV_VARIABLES should include '"BUN_CONFIG_TOKEN":"edge-token"' | ||
| The variable RENOVATE_CUSTOM_ENV_VARIABLES should include '"ARTIFACTORY_ACCESS_TOKEN":"edge-token"' | ||
| The variable RENOVATE_CUSTOM_ENV_VARIABLES should include '"ARTIFACTORY_USERNAME":"test-user"' | ||
| End | ||
|
|
||
| It 'keeps values set by the caller' | ||
| export RENOVATE_REPOSITORIES="my-org/other-repo" | ||
| export RENOVATE_ONBOARDING="true" | ||
| export RENOVATE_SECRETS='{"OTHER":"value"}' | ||
| export RENOVATE_CUSTOM_ENV_VARIABLES='{"BUN_CONFIG_TOKEN":"override"}' | ||
| When call export_renovate_config | ||
| The status should be success | ||
| The output should include "Renovate repositories: my-org/other-repo" | ||
| The variable RENOVATE_ONBOARDING should equal "true" | ||
| The variable RENOVATE_SECRETS should equal '{"REPOX_TOKEN":"saas-token","OTHER":"value"}' | ||
| The variable RENOVATE_CUSTOM_ENV_VARIABLES should include '"BUN_CONFIG_TOKEN":"override"' | ||
| End | ||
| End | ||
|
|
||
| Describe 'main()' | ||
| It 'installs and runs Renovate' | ||
| When run script renovate/renovate.sh | ||
| The status should be success | ||
| The line 1 should equal "::group::Install Renovate" | ||
| The output should include "::endgroup::" | ||
| The output should include "mise exec node@24.11.0 -- $RUNNER_TEMP/renovate/node_modules/.bin/renovate" | ||
| End | ||
|
|
||
| It 'fails without a GitHub token' | ||
| export RENOVATE_TOKEN="" | ||
| When run script renovate/renovate.sh | ||
| The status should be failure | ||
| The error should include "RENOVATE_TOKEN" | ||
| End | ||
| End |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Bug: Usage example omits contents: read, so checkout fails on private repos
The usage example's job-level
permissions:block grants onlyid-token: write. Once any permission is listed, every permission that isn't listed is set tonone. That leaves the job'sGITHUB_TOKENwithoutcontents: read, so theactions/checkoutstep fails on private repositories. Private repos are a primary target here, sinceprivate-readeris the default role. The action needs that checkout because mise installs tools from the repository's mise config. Other examples in this README that run checkout grantcontents: readalongsideid-token: write. Add it here as well, and list it under Required GitHub Permissions.Grant contents: read so actions/checkout can clone the repository:
Was this helpful? React with 👍 / 👎