Skip to content

Gerrit Verify

Gerrit Verify #422

---
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: 2026 The Linux Foundation
# Gerrit-triggered verify pipeline for cps.
#
# gerrit_to_platform dispatches this workflow (via the GitHub API) when a
# patchset is created (or on a `recheck` comment); it then votes Verified
# +/-1 on the change.
#
# Discovery is filename-convention based: the name contains BOTH 'gerrit'
# AND 'verify', so gerrit_to_platform dispatches it on patchset-created.
# The file must exist on every active branch (dispatch targets
# refs/heads/{GERRIT_BRANCH}); this deployment covers `master`.
#
# Both the Maven verify lane and the SonarCloud lane live in this one
# file, and that is deliberate. gerrit_to_platform dispatches EVERY
# workflow whose filename matches, so the previous split across
# gerrit-verify.yaml and gerrit-sonar-verify.yaml produced two runs, each
# with its own clear-vote/vote pair, both authenticating as the same
# Gerrit account (GERRIT_SSH_USER). Gerrit keeps one value per account
# per label, so the slower run simply overwrote the faster one: a failing
# build could be masked by a passing scan. One workflow, one clear, one
# vote, and the conclusion covers every lane.
name: 'Gerrit Verify'
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
inputs:
GERRIT_BRANCH:
description: 'Branch that change is against'
required: false
type: string
default: ''
GERRIT_CHANGE_ID:
description: 'The ID for the change'
required: false
type: string
default: ''
GERRIT_CHANGE_NUMBER:
description: 'The Gerrit number'
required: false
type: string
default: ''
GERRIT_CHANGE_URL:
description: 'URL to the change'
required: false
type: string
default: ''
GERRIT_EVENT_TYPE:
description: 'Type of Gerrit event'
required: false
type: string
default: ''
GERRIT_PATCHSET_NUMBER:
description: 'The patch number for the change'
required: false
type: string
default: ''
GERRIT_PATCHSET_REVISION:
description: 'The revision sha'
required: false
type: string
default: ''
GERRIT_PROJECT:
description: 'Project in Gerrit'
required: false
type: string
default: ''
GERRIT_REFSPEC:
description: 'Gerrit refspec of change'
required: false
type: string
default: ''
GERRIT_DISABLED:
description: 'Run without Gerrit components'
required: false
default: false
type: boolean
concurrency:
# Group on the Gerrit change when there is one, so a new patchset
# supersedes the run for its predecessor. Fall back to the ref rather
# than github.run_id: run_id is unique per run, so cancel-in-progress
# could never fire for a manual dispatch, and three full-reactor
# builds were seen competing for runners at once.
#
# The workflow name is part of the group because the group is
# repository-wide, and the CLM lane must not cancel this one.
# yamllint disable-line rule:line-length
group: '${{ github.workflow }}-${{ github.event.inputs.GERRIT_CHANGE_ID || github.ref }}'
cancel-in-progress: true
permissions: {}
jobs:
# Clear any previous Verified vote so the change starts from a clean
# state on each patchset/recheck. One clear for the whole workflow:
# every lane below reports through the single vote job at the end.
clear-vote:
name: 'Clear Gerrit Vote'
if: inputs.GERRIT_DISABLED != true
runs-on: ubuntu-latest
permissions:
contents: read
timeout-minutes: 5
steps:
- name: 'Harden runner'
# yamllint disable-line rule:line-length
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with:
egress-policy: audit
- name: 'Clear votes'
# yamllint disable-line rule:line-length
uses: lfreleng-actions/gerrit-review-action@1e3eae766b3de755a2e87aa216cedebbaf9c8292 # v1.1.3
with:
host: ${{ vars.GERRIT_SERVER }}
username: ${{ vars.GERRIT_SSH_USER }}
key: ${{ secrets.GERRIT_SSH_PRIVKEY }} # zizmor: ignore[secrets-outside-env]
known_hosts: ${{ vars.GERRIT_KNOWN_HOSTS }}
gerrit-change-number: ${{ inputs.GERRIT_CHANGE_NUMBER }}
gerrit-patchset-number: ${{ inputs.GERRIT_PATCHSET_NUMBER }}
vote-type: clear
- name: 'Allow replication'
run: sleep 10s
# Call the reusable Maven verify lane. When dispatched by Gerrit the
# gerrit_* inputs drive the reusable workflow's Gerrit-aware checkout;
# for a manual GERRIT_DISABLED run they are blanked so it falls back to
# a standard checkout of the calling repository.
#
# Pinned to v0.2.1. The job timeouts introduced in v0.0.4 remain the
# reason this lane completes at all: build 45 minutes, and 30 each for
# tests, SBOM and Grype. The fixed 10 minutes before that killed this
# reactor at module 18 of 24 while it was still compiling. A full run
# now builds in a little under 15 minutes, so the defaults suit cps
# with room to spare and nothing is set below; pass
# build_timeout_minutes if the reactor outgrows them.
#
# v0.1.0 added optional build artefact publication and removed a dead
# github_summary input that produced a warning annotation on every
# run. upload_build_artifacts stays off here deliberately: nothing
# downstream consumes the jars yet, and uploading a 24-module reactor
# on every patchset would cost storage for no reader. Turn it on when
# a merge, stage or container lane needs the output.
#
# v0.1.2 carries maven-build-action v0.3.1, which stops that action
# leaving a Maven settings document in the workspace. This lane builds
# the code under review, so a credentials file left there was readable
# by the plugins and tests of the patchset being verified.
build-test:
name: 'Maven Build/Test'
needs: clear-vote
if: >-
always()
&& (needs.clear-vote.result == 'success'
|| needs.clear-vote.result == 'skipped')
permissions:
contents: read
pull-requests: read # repository-metadata-action queries PR data
# yamllint disable-line rule:line-length
uses: lfreleng-actions/java-workflows/.github/workflows/maven-build-test.yaml@ed7e52b3ecc60198db8df758fad01b7d688b8ed3 # v0.3.0
with:
# master stream builds on Java 21 (paris/Java 17 handled separately).
java_version: '21'
# Skip Jib container image builds during verify; the merge/stage
# lanes own image publication.
#
# docker.pull.registry has no default in the cps POMs: Jenkins
# supplies it through the managed settings.xml, so a build without
# one leaves ${docker.pull.registry} unsubstituted and the
# Testcontainers specs in cps-ncmp-service and cps-ri fail to pull
# their Kafka and PostgreSQL images. Sourced from the organisation
# variable rather than hardcoded, with the current value as a
# fallback. Note this is CONTAINER_PUBLIC_REGISTRY (10001, the
# Docker Hub proxy) and NOT the similarly named
# CONTAINER_PULL_REGISTRY, which serves a different repository and
# returns 404 for these images. docker.push.registry goes unused
# while Jib is skipped, and is set only to keep the property
# resolved across the reactor.
# yamllint disable-line rule:line-length
mvn_params: "-Djib.skip=true -Ddocker.pull.registry=${{ vars.CONTAINER_PUBLIC_REGISTRY || 'nexus3.onap.org:10001' }} -Ddocker.push.registry=${{ vars.CONTAINER_PUSH_REGISTRY || 'nexus3.onap.org:10002' }}"
# Run the build job's harden-runner in audit while the egress
# footprint is characterised, then tighten to block.
build_permit_egress_traffic: true
# Grype does not report CVEs on this lane. The cps project
# leadership asked that dependency-risk findings surface in the
# CLM scan lane (gerrit-clm.yaml) instead, so grype_permit_fail
# goes with the scan.
#
# SBOM generation stays on. The European Union legally mandates
# Software Bill of Materials generation under the Cyber
# Resilience Act:
# https://www.cyberresilienceact.eu/explained.html
#
# grype_enabled is the flag for this rather than sbom_enabled:
# upstream decouples the two one way only, so this drops the
# audit and keeps the document, where sbom_enabled would remove
# both.
grype_enabled: false
# Gerrit-aware checkout inputs. Blanked on a GERRIT_DISABLED manual
# run so the reusable workflow performs a normal checkout.
# yamllint disable-line rule:line-length
gerrit_refspec: ${{ !inputs.GERRIT_DISABLED && inputs.GERRIT_REFSPEC || '' }}
# yamllint disable-line rule:line-length
gerrit_project: ${{ !inputs.GERRIT_DISABLED && inputs.GERRIT_PROJECT || '' }}
# yamllint disable-line rule:line-length
gerrit_branch: ${{ !inputs.GERRIT_DISABLED && inputs.GERRIT_BRANCH || '' }}
# gerrit_url falls back to the GERRIT_URL repository variable.
# SonarCloud analysis, running in parallel with the Maven lane above.
# Both build the full reactor, so running them concurrently keeps the
# wall clock at roughly one build rather than two.
#
# The scan publishes to a short-lived branch named for the change and
# patchset, so SonarCloud reports the patchset under review rather
# than the target branch.
#
# A failing quality gate fails this lane, which votes Verified-1.
sonar:
name: 'SonarQube Cloud'
needs: clear-vote
if: >-
always()
&& (needs.clear-vote.result == 'success'
|| needs.clear-vote.result == 'skipped')
permissions:
contents: read
# yamllint disable-line rule:line-length
uses: lfreleng-actions/security-workflows/.github/workflows/sonarqube-cloud.yaml@7483557cf53b18109e679b8a3da42ce8e6dff219 # v0.8.0
with:
sonar_organization: 'onap'
sonar_project_key: 'onap_cps'
# yamllint disable-line rule:line-length
sonar_branch_name: ${{ (!inputs.GERRIT_DISABLED && inputs.GERRIT_CHANGE_NUMBER != '') && format('{0}-{1}', inputs.GERRIT_CHANGE_NUMBER, inputs.GERRIT_PATCHSET_NUMBER) || format('manual-{0}', github.run_id) }}
# yamllint disable-line rule:line-length
sonar_branch_target: ${{ inputs.GERRIT_BRANCH != '' && inputs.GERRIT_BRANCH || 'master' }}
build_type: 'maven'
mvn_phases: 'clean install'
mvn_params: '-Djib.skip=true'
wait_for_quality_gate: true
fail_on_quality_gate: true
timeout_minutes: 90
build_permit_egress_traffic: true
# yamllint disable-line rule:line-length
gerrit_refspec: ${{ !inputs.GERRIT_DISABLED && inputs.GERRIT_REFSPEC || '' }}
# yamllint disable-line rule:line-length
gerrit_project: ${{ !inputs.GERRIT_DISABLED && inputs.GERRIT_PROJECT || '' }}
# yamllint disable-line rule:line-length
gerrit_branch: ${{ !inputs.GERRIT_DISABLED && inputs.GERRIT_BRANCH || '' }}
secrets:
sonar_token: ${{ secrets.SONAR_TOKEN }}
maven_global_settings: ${{ vars.MVN_GLOBAL_SETTINGS }}
# Report the overall workflow conclusion back to Gerrit as a Verified
# vote. workflow-conclusion aggregates every job in the run, so this
# single vote covers both lanes above.
vote:
name: 'Report Status to Gerrit'
if: ${{ always() && inputs.GERRIT_DISABLED != true }}
needs: [clear-vote, build-test, sonar]
runs-on: ubuntu-latest
permissions:
contents: read
actions: read # workflow-conclusion lists run jobs via the API
timeout-minutes: 5
steps:
- name: 'Harden runner'
# yamllint disable-line rule:line-length
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with:
egress-policy: audit
- name: 'Get workflow conclusion'
# yamllint disable-line rule:line-length
uses: im-open/workflow-conclusion@8eac7f17381a6917bc04fec3e2c92e70ebc37526 # v3.0.0
- name: 'Set vote'
# yamllint disable-line rule:line-length
uses: lfreleng-actions/gerrit-review-action@1e3eae766b3de755a2e87aa216cedebbaf9c8292 # v1.1.3
with:
host: ${{ vars.GERRIT_SERVER }}
username: ${{ vars.GERRIT_SSH_USER }}
key: ${{ secrets.GERRIT_SSH_PRIVKEY }} # zizmor: ignore[secrets-outside-env]
known_hosts: ${{ vars.GERRIT_KNOWN_HOSTS }}
gerrit-change-number: ${{ inputs.GERRIT_CHANGE_NUMBER }}
gerrit-patchset-number: ${{ inputs.GERRIT_PATCHSET_NUMBER }}
vote-type: ${{ env.WORKFLOW_CONCLUSION }}