Skip to content

Commit 7f6d13a

Browse files
authored
Merge pull request #11119 from Alexey-Rivkin/blossom_secure_flow
CI: Add Blossom secure flow
2 parents 0a4759c + c17f7c4 commit 7f6d13a

File tree

3 files changed

+327
-0
lines changed

3 files changed

+327
-0
lines changed

.ci/jenkins/Jenkinsfile.github

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/groovy
2+
3+
/**
4+
* Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2026. ALL RIGHTS RESERVED.
5+
* See file LICENSE for terms.
6+
*/
7+
8+
@Library('blossom-github-lib@master')
9+
@Library('github.com/Mellanox/ci-demo@master')
10+
def matrix = new com.mellanox.cicd.Matrix()
11+
12+
import ipp.blossom.*
13+
14+
def githubHelper = null
15+
def blueOceanUrl = ""
16+
def currentPrNumber = null
17+
18+
if (params.githubData) {
19+
withCredentials([usernamePassword(credentialsId: 'github-token', passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
20+
githubHelper = GithubHelper.getInstance("${GIT_PASSWORD}", params.githubData)
21+
}
22+
currentPrNumber = githubHelper.getPRNumber()?.toString()
23+
24+
// Abort previous running builds of the same PR
25+
if (currentPrNumber) {
26+
def slurper = new groovy.json.JsonSlurper()
27+
try {
28+
Jenkins.instance.getItemByFullName(env.JOB_NAME).builds.findAll {
29+
it.isBuilding() && it.number < currentBuild.number
30+
}.each { b ->
31+
def gd = b.getAction(hudson.model.ParametersAction)?.getParameters()?.find { it.name == 'githubData' }?.value
32+
if (gd && slurper.parseText(gd)?.pr?.toString() == currentPrNumber) {
33+
echo "Aborting build #${b.number} for same PR #${currentPrNumber}"
34+
b.doStop()
35+
}
36+
}
37+
} catch (Exception e) {
38+
echo "Could not abort previous builds: ${e.message}"
39+
}
40+
}
41+
42+
def blueOceanJobPath = env.JOB_NAME.replace('/', '%2F')
43+
blueOceanUrl = "${JENKINS_URL}blue/organizations/jenkins/${blueOceanJobPath}/detail/${env.JOB_BASE_NAME}/${env.BUILD_NUMBER}/pipeline/"
44+
45+
githubHelper.updateCommitStatus(blueOceanUrl, "CI started", GitHubCommitState.PENDING, env.JOB_BASE_NAME)
46+
currentBuild.description = githubHelper.getBuildDescription()
47+
}
48+
49+
try {
50+
matrix.main()
51+
} catch (Exception ex) {
52+
println ex
53+
throw ex
54+
} finally {
55+
if (params.githubData) {
56+
githubHelper.updateCommitStatus(
57+
blueOceanUrl,
58+
"CI completed",
59+
currentBuild.resultIsBetterOrEqualTo('SUCCESS') ? GitHubCommitState.SUCCESS : GitHubCommitState.FAILURE,
60+
env.JOB_BASE_NAME
61+
)
62+
githubHelper.uploadLogs(this, env.JOB_NAME, env.BUILD_NUMBER, null, null)
63+
}
64+
}

.ci/jenkins/proj_jjb_github.yaml

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2026. ALL RIGHTS RESERVED.
2+
# See file LICENSE for terms.
3+
#
4+
# Jenkins Job Builder (JJB) configuration for UCX GitHub (Blossom) jobs
5+
#
6+
# Entry point: ucx-dispatcher-github (generic-webhook-trigger token must match job name)
7+
# Leaf jobs: ucx-*-github (triggered by dispatcher, not directly from GitHub)
8+
#
9+
# NOTE: This file is applied by DevOps to Jenkins.
10+
11+
- job-template:
12+
name: "{jjb_proj}-dispatcher-github"
13+
folder: "UCX-GitHub"
14+
project-type: pipeline
15+
properties:
16+
- github:
17+
url: "https://github.com/openucx/ucx"
18+
- build-discarder:
19+
days-to-keep: 14
20+
num-to-keep: 1000
21+
- inject:
22+
keep-system-variables: true
23+
properties-content: |
24+
jjb_proj={jjb_proj}-dispatcher-github
25+
triggers:
26+
- generic-webhook-trigger:
27+
token: "{jjb_proj}-dispatcher-github"
28+
print-contributors: true
29+
print-posted-content: true
30+
silent-response: false
31+
cause: "GitHub Blossom trigger"
32+
post-content-params:
33+
- type: JSONPath
34+
key: githubData
35+
value: $
36+
- type: JSONPath
37+
key: VARIABLE_FROM_POST
38+
value: $
39+
description: "UCX GitHub dispatcher (Blossom). Do NOT edit via Web GUI!"
40+
concurrent: true
41+
sandbox: true
42+
parameters:
43+
- string:
44+
name: "VARIABLE_FROM_POST"
45+
default: ""
46+
description: "Raw GitHub webhook payload (Blossom)"
47+
dsl: |
48+
@Library('blossom-github-lib@master')
49+
import ipp.blossom.*
50+
51+
def githubHelper = null
52+
withCredentials([usernamePassword(credentialsId: 'github-token', passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {{
53+
githubHelper = GithubHelper.getInstance("${{GIT_PASSWORD}}", VARIABLE_FROM_POST)
54+
}}
55+
56+
def sha = githubHelper.getMergedSHA()
57+
58+
currentBuild.description = githubHelper.getBuildDescription()
59+
60+
def jobs = [
61+
'ucx-codestyle-github',
62+
'ucx-static-checks-github',
63+
'ucx-coverity-github',
64+
'ucx-build-github',
65+
'ucx-build-static-github',
66+
]
67+
68+
def fanout = [:]
69+
for (def j in jobs) {{
70+
def jobName = "UCX-GitHub/${{j}}"
71+
fanout[jobName] = {{
72+
build job: jobName, parameters: [
73+
string(name: 'sha1', value: sha),
74+
string(name: 'githubData', value: VARIABLE_FROM_POST),
75+
], propagate: false, wait: true
76+
}}
77+
}}
78+
parallel fanout
79+
80+
- job-template:
81+
name: "{jjb_proj}"
82+
folder: "UCX-GitHub"
83+
project-type: pipeline
84+
disabled: false
85+
properties:
86+
- github:
87+
url: "https://github.com/openucx/ucx"
88+
- build-discarder:
89+
days-to-keep: 14
90+
num-to-keep: 1000
91+
- inject:
92+
keep-system-variables: true
93+
properties-content: |
94+
jjb_proj={jjb_proj}
95+
description: "{jjb_description}"
96+
concurrent: true
97+
sandbox: true
98+
parameters:
99+
- string:
100+
name: "sha1"
101+
default: "master"
102+
description: "Git ref/commit to build, set by dispatcher"
103+
- string:
104+
name: "githubData"
105+
default: ""
106+
description: "Webhook payload from Blossom"
107+
- string:
108+
name: "conf_file"
109+
default: "{jjb_conf_file}"
110+
description: "Matrix config file"
111+
- bool:
112+
name: "build_dockers"
113+
default: false
114+
description: "Force rebuild docker containers (if supported)"
115+
- string:
116+
name: "DEBUG"
117+
default: 0
118+
description: "Enable debug prints and traces, valid values are 0-9"
119+
pipeline-scm:
120+
scm:
121+
- git:
122+
url: "https://github.com/openucx/ucx.git"
123+
branches: [ '$sha1' ]
124+
shallow-clone: false
125+
do-not-fetch-tags: false
126+
refspec: "+refs/heads/*:refs/remotes/origin/* +refs/pull/*:refs/remotes/origin/pr/* +refs/tags/*:refs/remotes/origin/tags/*"
127+
browser: githubweb
128+
browser-url: "https://github.com/openucx/ucx"
129+
script-path: ".ci/jenkins/Jenkinsfile.github"
130+
131+
- project:
132+
name: ucx-dispatcher-github
133+
jjb_proj: "ucx"
134+
jobs:
135+
- "{jjb_proj}-dispatcher-github"
136+
137+
- project:
138+
name: ucx-codestyle-github
139+
jjb_proj: "ucx-codestyle-github"
140+
jjb_conf_file: ".ci/pipeline/codestyle_matrix.yaml"
141+
jjb_description: "UCX Codestyle checks (GitHub Blossom). Do NOT edit via Web GUI!"
142+
jobs:
143+
- "{jjb_proj}"
144+
145+
- project:
146+
name: ucx-static-checks-github
147+
jjb_proj: "ucx-static-checks-github"
148+
jjb_conf_file: ".ci/pipeline/static_checks_matrix.yaml"
149+
jjb_description: "UCX Static checks (GitHub Blossom). Do NOT edit via Web GUI!"
150+
jobs:
151+
- "{jjb_proj}"
152+
153+
- project:
154+
name: ucx-coverity-github
155+
jjb_proj: "ucx-coverity-github"
156+
jjb_conf_file: ".ci/pipeline/coverity_matrix.yaml"
157+
jjb_description: "UCX Coverity (GitHub Blossom). Do NOT edit via Web GUI!"
158+
jobs:
159+
- "{jjb_proj}"
160+
161+
- project:
162+
name: ucx-build-github
163+
jjb_proj: "ucx-build-github"
164+
jjb_conf_file: ".ci/pipeline/build_matrix.yaml"
165+
jjb_description: "UCX Build job (GitHub Blossom). Do NOT edit via Web GUI!"
166+
jobs:
167+
- "{jjb_proj}"
168+
169+
- project:
170+
name: ucx-build-static-github
171+
jjb_proj: "ucx-build-static-github"
172+
jjb_conf_file: ".ci/pipeline/build_static_matrix.yaml"
173+
jjb_description: "UCX Static build (GitHub Blossom). Do NOT edit via Web GUI!"
174+
jobs:
175+
- "{jjb_proj}"

.github/workflows/blossom-ci.yml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2026. ALL RIGHTS RESERVED.
2+
# See file LICENSE for terms.
3+
4+
# A workflow to trigger ci on hybrid infra (github + self hosted runner)
5+
6+
name: Blossom-CI
7+
run-name: >
8+
${{ github.event_name == 'workflow_dispatch' &&
9+
format(
10+
'Blossom CI: {0}{1} PR #{2}',
11+
fromJson(github.event.inputs.args).job,
12+
fromJson(github.event.inputs.args).build && format(' #{0}', fromJson(github.event.inputs.args).build) || '',
13+
fromJson(github.event.inputs.args).pr
14+
)
15+
|| '' }}
16+
on:
17+
issue_comment:
18+
types: [created]
19+
workflow_dispatch:
20+
inputs:
21+
platform:
22+
description: 'runs-on argument'
23+
required: false
24+
args:
25+
description: 'argument'
26+
required: false
27+
jobs:
28+
Authorization:
29+
name: Authorization
30+
runs-on: blossom
31+
outputs:
32+
args: ${{ env.args }}
33+
34+
# This job only runs for pull request comments
35+
if: github.event.comment.body == '/build'
36+
steps:
37+
- name: Check if comment is issued by authorized person
38+
run: blossom-ci
39+
env:
40+
OPERATION: 'AUTH'
41+
REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42+
REPO_KEY_DATA: ${{ secrets.BLOSSOM_KEY }}
43+
44+
Vulnerability-scan:
45+
name: Vulnerability scan
46+
needs: [Authorization]
47+
runs-on: ubuntu-latest
48+
steps:
49+
- name: Checkout code
50+
uses: actions/checkout@v2
51+
with:
52+
repository: ${{ fromJson(needs.Authorization.outputs.args).repo }}
53+
ref: ${{ fromJson(needs.Authorization.outputs.args).ref }}
54+
lfs: 'true'
55+
56+
- name: Run blossom action
57+
uses: NVIDIA/blossom-action@main
58+
env:
59+
REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
60+
REPO_KEY_DATA: ${{ secrets.BLOSSOM_KEY }}
61+
with:
62+
args1: ${{ fromJson(needs.Authorization.outputs.args).args1 }}
63+
args2: ${{ fromJson(needs.Authorization.outputs.args).args2 }}
64+
args3: ${{ fromJson(needs.Authorization.outputs.args).args3 }}
65+
66+
Job-trigger:
67+
name: Start ci job
68+
needs: [Vulnerability-scan]
69+
runs-on: blossom
70+
steps:
71+
- name: Start ci job
72+
run: blossom-ci
73+
env:
74+
OPERATION: 'START-CI-JOB'
75+
CI_SERVER: ${{ secrets.CI_SERVER }}
76+
REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77+
78+
Upload-Log:
79+
name: Upload log
80+
runs-on: blossom
81+
if: github.event_name == 'workflow_dispatch'
82+
steps:
83+
- name: Jenkins log for pull request ${{ fromJson(github.event.inputs.args).pr }} (click here)
84+
run: blossom-ci
85+
env:
86+
OPERATION: 'POST-PROCESSING'
87+
CI_SERVER: ${{ secrets.CI_SERVER }}
88+
REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)