Skip to content

Commit ccc0f92

Browse files
committed
Publish wheels on github
1 parent 26db20b commit ccc0f92

File tree

1 file changed

+101
-67
lines changed

1 file changed

+101
-67
lines changed

.github/workflows/build-ubuntu.yml

Lines changed: 101 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ name: Build Ubuntu
55

66
on:
77
push:
8-
branches: [ main, 'release/*.*.x' ]
8+
branches: [ main, 'release/*.*.x', 'aaristarkhov/kitmaker' ]
99
tags: [ 'v*' ]
1010
pull_request:
1111

@@ -24,7 +24,7 @@ jobs:
2424

2525
strategy:
2626
matrix:
27-
build_type: ["Debug", "Release"]
27+
build_type: ["Release"]
2828
python_version: ['3.10', '3.11', '3.12']
2929
arch: ['x64', 'arm64']
3030

@@ -103,6 +103,7 @@ jobs:
103103
with:
104104
name: isaacteleop-wheels-${{ matrix.arch }}-py${{ matrix.python_version }}
105105
path: install/wheels/*.whl
106+
if-no-files-found: error
106107
retention-days: 1
107108

108109
test-cloudxr:
@@ -216,12 +217,17 @@ jobs:
216217
-p "${ARTIFACTORY_API_KEY}" \
217218
"${wheels[@]}"
218219
219-
kitmaker:
220-
runs-on: [self-hosted, linux]
220+
publish-github-release-assets:
221+
runs-on: ubuntu-latest
221222
needs:
222-
- publish-wheel
223-
environment: release
224-
if: ${{ needs.publish-wheel.result == 'success' }}
223+
- build-ubuntu
224+
# - test-cloudxr
225+
outputs:
226+
wheel_urls: ${{ steps.upload-release-assets.outputs.wheel_urls }}
227+
permissions:
228+
contents: write
229+
# Publish only after build and CloudXR tests succeed.
230+
if: ${{ github.event_name == 'push' && needs.build-ubuntu.result == 'success' }} # && needs.test-cloudxr.result == 'success'
225231

226232
steps:
227233
- name: Download wheel artifacts
@@ -231,82 +237,110 @@ jobs:
231237
merge-multiple: true
232238
path: wheels
233239

234-
- name: Submit wheel release to Kitmaker
240+
- name: Upload wheel(s) as GitHub release assets
241+
id: upload-release-assets
235242
env:
236-
KITMAKER_PROJECT_ID: ${{ secrets.KITMAKER_PROJECT_ID }}
237-
KITMAKER_TOKEN: ${{ secrets.KITMAKER_TOKEN }}
238-
KITMAKER_PIC_EMAIL: ${{ secrets.KITMAKER_PIC_EMAIL }}
239-
ARTIFACTORY_DOMAIN: ${{ secrets.ARTIFACTORY_DOMAIN }}
240-
ARTIFACTORY_REPO: ${{ secrets.ARTIFACTORY_REPO }}
241-
ARTIFACTORY_TOKEN: ${{ secrets.ARTIFACTORY_TOKEN }}
242-
ARTIFACTORY_USER: ${{ secrets.ARTIFACTORY_USER }}
243+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
244+
GH_REPO: ${{ github.repository }}
243245
run: |
244246
set -euo pipefail
245247
246-
if [[ -z "${KITMAKER_TOKEN}" || -z "${KITMAKER_PIC_EMAIL}" ]]; then
247-
echo "Missing one or more required secrets: KITMAKER_TOKEN, KITMAKER_PIC_EMAIL"
248+
shopt -s nullglob
249+
wheels=(wheels/*.whl)
250+
if (( ${#wheels[@]} == 0 )); then
251+
echo "No wheels found under wheels/*.whl"
252+
ls -la wheels || true
248253
exit 1
249254
fi
250255
251-
if [[ -z "${ARTIFACTORY_DOMAIN}" || -z "${ARTIFACTORY_REPO}" || -z "${ARTIFACTORY_TOKEN}" ]]; then
252-
echo "Missing one or more required secrets: ARTIFACTORY_DOMAIN, ARTIFACTORY_REPO, ARTIFACTORY_TOKEN"
253-
exit 1
254-
fi
256+
tag="ci-wheels-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
257+
title="CI Wheels ${GITHUB_RUN_ID}.${GITHUB_RUN_ATTEMPT}"
258+
259+
gh release create "${tag}" \
260+
--repo "${GH_REPO}" \
261+
--target "${GITHUB_SHA}" \
262+
--title "${title}" \
263+
--notes "Automated wheel artifacts for ${GITHUB_SHA}" \
264+
--draft
255265
256-
if [[ "${ARTIFACTORY_DOMAIN}" == http://* || "${ARTIFACTORY_DOMAIN}" == https://* ]]; then
257-
echo "ARTIFACTORY_DOMAIN must be hostname only (no scheme), e.g. artifactory.example.com"
266+
echo "Uploading ${#wheels[@]} wheel(s) to release ${tag}"
267+
gh release upload "${tag}" "${wheels[@]}" --repo "${GH_REPO}"
268+
269+
echo "Finalizing release ${tag} as pre-release"
270+
gh release edit "${tag}" --repo "${GH_REPO}" --draft=false --prerelease
271+
272+
echo "Uploaded assets on ${tag}:"
273+
release_assets_json="$(gh release view "${tag}" --repo "${GH_REPO}" --json assets)"
274+
echo "${release_assets_json}"
275+
276+
wheel_urls="$(jq -r '.assets[] | select(.name | endswith(".whl")) | .url' <<< "${release_assets_json}")"
277+
if [[ -z "${wheel_urls}" ]]; then
278+
echo "Unable to find wheel asset URLs in uploaded release assets"
258279
exit 1
259280
fi
260281
261-
if [[ "${ARTIFACTORY_DOMAIN}" == */* ]]; then
262-
echo "ARTIFACTORY_DOMAIN must not contain '/'"
282+
{
283+
echo "wheel_urls<<EOF"
284+
echo "${wheel_urls}"
285+
echo "EOF"
286+
} >> "$GITHUB_OUTPUT"
287+
288+
kitmaker:
289+
runs-on: [self-hosted, linux]
290+
needs:
291+
- publish-github-release-assets
292+
environment: release
293+
permissions:
294+
contents: read
295+
if: ${{ needs.publish-github-release-assets.result == 'success' }}
296+
297+
steps:
298+
- name: Submit wheel release to Kitmaker
299+
env:
300+
KITMAKER_PROJECT_ID: ${{ secrets.KITMAKER_PROJECT_ID }}
301+
KITMAKER_TOKEN: ${{ secrets.KITMAKER_TOKEN }}
302+
KITMAKER_PIC_EMAIL: ${{ secrets.KITMAKER_PIC_EMAIL }}
303+
WHEEL_URLS: ${{ needs.publish-github-release-assets.outputs.wheel_urls }}
304+
run: |
305+
set -euo pipefail
306+
307+
if [[ -z "${KITMAKER_TOKEN}" || -z "${KITMAKER_PIC_EMAIL}" ]]; then
308+
echo "Missing one or more required secrets: KITMAKER_TOKEN, KITMAKER_PIC_EMAIL"
263309
exit 1
264310
fi
265311
266-
shopt -s nullglob
267-
wheels=(wheels/*.whl)
268-
if (( ${#wheels[@]} == 0 )); then
269-
echo "No wheels found under wheels/*.whl"
270-
ls -la wheels || true
312+
if [[ -z "${WHEEL_URLS}" ]]; then
313+
echo "No wheel URLs were produced by publish-github-release-assets job"
271314
exit 1
272315
fi
273316
274317
api_url="https://kitmaker-portal.nvidia.com/api/v0/projects/${KITMAKER_PROJECT_ID}/releases"
275-
wheel_url_base="https://${ARTIFACTORY_USER}:${ARTIFACTORY_TOKEN}@${ARTIFACTORY_DOMAIN}/artifactory/${ARTIFACTORY_REPO}/isaacteleop"
276-
277-
for wheel_path in "${wheels[@]}"; do
278-
wheel_name="$(basename "${wheel_path}")"
279-
if [[ "${wheel_name}" =~ ^isaacteleop-([^-]+)- ]]; then
280-
wheel_version="${BASH_REMATCH[1]}"
281-
else
282-
echo "Unable to parse version from wheel filename: ${wheel_name}"
283-
exit 1
284-
fi
285-
286-
wheel_url="${wheel_url_base}/${wheel_version}/${wheel_name}"
318+
payload_items=()
319+
while IFS= read -r wheel_url; do
320+
[[ -z "${wheel_url}" ]] && continue
321+
wheel_name="$(basename "${wheel_url}")"
322+
echo "Queueing wheel for Kitmaker payload: ${wheel_name}"
323+
324+
payload_items+=("$(jq -cn \
325+
--arg pic "${KITMAKER_PIC_EMAIL}" \
326+
--arg url "${wheel_url}" \
327+
'{pic: $pic, job_type: "wheel-release-job", publish_to: "both_devzone_pypi", url: $url, size: "small", upload: false}')")
328+
done <<< "${WHEEL_URLS}"
329+
330+
if (( ${#payload_items[@]} == 0 )); then
331+
echo "No valid wheel URLs found to submit to Kitmaker"
332+
exit 1
333+
fi
287334
288-
payload=$(cat <<EOF
289-
{
290-
"project_name": "isaacteleop",
291-
"payload": [
292-
{
293-
"pic": "${KITMAKER_PIC_EMAIL}",
294-
"job_type": "wheel-release-job",
295-
"publish_to": "both_devzone_pypi",
296-
"url": "${wheel_url}",
297-
"size": "small",
298-
"upload": false
299-
}
300-
]
301-
}
302-
EOF
303-
)
304-
305-
echo "Posting wheel to Kitmaker: ${wheel_name}"
306-
curl --fail-with-body --show-error --silent --location --include \
307-
-X POST "${api_url}" \
308-
-H "Authorization: Bearer ${KITMAKER_TOKEN}" \
309-
-H "Content-Type: application/json" \
310-
-d "${payload}"
311-
echo
312-
done
335+
payload_array="$(printf '%s\n' "${payload_items[@]}" | jq -s '.')"
336+
payload="$(jq -cn --arg project_name "isaacteleop" --argjson payload "${payload_array}" '{project_name: $project_name, payload: $payload}')"
337+
338+
echo "Posting ${#payload_items[@]} wheel(s) to Kitmaker in a single request"
339+
curl --fail-with-body --show-error --silent --location --include \
340+
-X POST "${api_url}" \
341+
-H "Authorization: Bearer ${KITMAKER_TOKEN}" \
342+
-H "Content-Type: application/json" \
343+
-d "${payload}"
344+
echo
345+
echo "Waiting 60 seconds to allow Kitmaker to start downloading wheel payload"
346+
sleep 60

0 commit comments

Comments
 (0)