Skip to content

Commit ced4b83

Browse files
authored
Merge pull request #42 from doanac/publishing-api
ci: Convert to a newer publishing API
2 parents b6fb4fa + 2f68a5d commit ced4b83

File tree

7 files changed

+160
-45
lines changed

7 files changed

+160
-45
lines changed

.github/workflows/build-daily.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99

1010
permissions:
1111
contents: read
12+
security-events: read # This is required to handle authentication to our artifact publishing API
1213

1314
jobs:
1415
build-daily:

.github/workflows/build-on-pr.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55

66
permissions:
77
contents: read
8+
security-events: read # This is required to handle authentication to our artifact publishing API
89

910
jobs:
1011
build-pr:

.github/workflows/build-on-push.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66

77
permissions:
88
contents: read
9+
security-events: read # This is required to handle authentication to our artifact publishing API
910

1011
jobs:
1112
build-daily:

.github/workflows/debos.yml

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ on:
1111
# permissions to none
1212
permissions:
1313
contents: read
14+
security-events: read # This is required to handle authentication to our artifact publishing API
1415

1516
env:
1617
# github runs are only unique per repository and may also be re-run; create a
@@ -31,7 +32,6 @@ jobs:
3132
container:
3233
image: debian:trixie
3334
volumes:
34-
- /srv/gh-runners/quic-yocto/builds:/fileserver-builds
3535
- /srv/gh-runners/quic-yocto/downloads:/fileserver-downloads
3636
options: --privileged
3737
steps:
@@ -95,30 +95,30 @@ jobs:
9595
9696
- name: Upload artifacts to fileserver space for builds
9797
id: upload_artifacts
98+
env:
99+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
98100
run: |
99101
set -ux
100-
# curl will be used to talk to fileserver; should be installed by
101-
# default
102-
apt -y install curl
102+
# python3-requests is used by publish_aritfacts.py
103+
apt -y install python3-requests
103104
# create a directory for the current run
104-
dir="/fileserver-builds/${BUILD_ID}"
105-
mkdir -vp "${dir}"
105+
export BUILD_DIR="/tmp/${BUILD_ID}"
106+
mkdir -vp "${BUILD_DIR}"
106107
# copy output files
107-
cp -av rootfs.tar.gz "${dir}"
108-
cp -av dtbs.tar.gz "${dir}"
109-
cp -av disk-ufs.img.gz "${dir}"
110-
cp -av disk-sdcard.img.gz "${dir}"
108+
cp -av rootfs.tar.gz "${BUILD_DIR}"
109+
cp -av dtbs.tar.gz "${BUILD_DIR}"
110+
cp -av disk-ufs.img.gz "${BUILD_DIR}"
111+
cp -av disk-sdcard.img.gz "${BUILD_DIR}"
111112
# TODO: separate flash_* directories between UFS and eMMC
112-
tar -cvf "${dir}"/flash-ufs.tar.gz \
113+
tar -cvf "${BUILD_DIR}"/flash-ufs.tar.gz \
113114
disk-ufs.img1 \
114115
disk-ufs.img2 \
115116
flash_rb3*
116-
tar -cvf "${dir}"/flash-emmc.tar.gz \
117+
tar -cvf "${BUILD_DIR}"/flash-emmc.tar.gz \
117118
disk-sdcard.img1 \
118119
disk-sdcard.img2 \
119120
flash_rb1*
120121
# instruct fileserver to publish this directory
121-
url="${FILESERVER_URL}/${BUILD_ID}/"
122-
curl -X POST -H 'Accept: text/event-stream' "${url}"
123-
echo "url=\"${url}\"" >> $GITHUB_OUTPUT
124-
122+
export URL="${FILESERVER_URL}/${BUILD_ID}/"
123+
.github/workflows/publish_artifacts.py
124+
echo Image available at: ${URL}

.github/workflows/linux.yml

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ on:
1111
# permissions to none
1212
permissions:
1313
contents: read
14+
security-events: read # This is required to handle authentication to our artifact publishing API
1415

1516
env:
1617
# where results will be posted/hosted
@@ -33,7 +34,6 @@ jobs:
3334
container:
3435
image: debian:trixie
3536
volumes:
36-
- /srv/gh-runners/quic-yocto/builds:/fileserver-builds
3737
- /srv/gh-runners/quic-yocto/downloads:/fileserver-downloads
3838
steps:
3939
- uses: actions/checkout@v4
@@ -64,19 +64,19 @@ jobs:
6464
scripts/build-linux-deb.sh kernel-configs/systemd-boot.config
6565
6666
- name: Upload results to fileserver
67+
env:
68+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6769
run: |
6870
set -ux
6971
# dcmd from devscripts will be used to parse .changes file
7072
apt -y install --no-install-recommends devscripts
71-
# curl will be used to talk to fileserver; should be installed by
72-
# default
73-
apt -y install curl
73+
# python3-requests is used by publish_aritfacts.py
74+
apt -y install python3-requests
7475
# copy to fileserver builds and downloads directories
75-
for dir in "/fileserver-builds/${BUILD_ID}" \
76-
"/fileserver-downloads/${BUILD_ID}"; do
77-
mkdir -vp "${dir}"
78-
cp -av `dcmd *.changes` "${dir}"
79-
done
76+
export BUILD_DIR="/fileserver-downloads/${BUILD_ID}"
77+
mkdir -vp "${BUILD_DIR}"
78+
cp -av `dcmd *.changes` "${BUILD_DIR}"
79+
8080
# create or update linux-deb-latest symlink
8181
mkdir -vp /fileserver-downloads/qcom-deb-images
8282
(
@@ -90,6 +90,7 @@ jobs:
9090
# perhaps help NFS sync
9191
sync
9292
# instruct fileserver to publish this directory
93-
url="${FILESERVER_URL}/${BUILD_ID}/"
94-
curl -X POST -H 'Accept: text/event-stream' "${url}"
93+
export URL="${FILESERVER_URL}/${BUILD_ID}/"
94+
.github/workflows/publish_artifacts.py
95+
echo Image available at: ${URL}
9596
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
3+
# SPDX-License-Identifier: BSD-3-Clause
4+
5+
from multiprocessing import Pool
6+
import os
7+
import sys
8+
from time import sleep
9+
from typing import List
10+
11+
import requests
12+
13+
gh_token = os.environ["GITHUB_TOKEN"]
14+
num_threads_str = os.environ.get("UPLOAD_THREADS", "5")
15+
16+
17+
def upload_file(args):
18+
"""
19+
Uploads a file to our file upload service. The service is a GCP CloudRun
20+
project that returns signed URLs to Google Storage objects we can upload to.
21+
"""
22+
try:
23+
url, base, name = args
24+
25+
headers = {
26+
"Authentication": f"Bearer {gh_token}",
27+
}
28+
29+
# Obtain the signed-url for GCS using Fibonacci backoff/retries
30+
for x in (1, 2, 3, 5, 0):
31+
r = requests.put(url, headers=headers, allow_redirects=False)
32+
if not r.ok:
33+
correlation_id = r.headers.get("X-Correlation-ID", "?")
34+
if not x:
35+
return (
36+
name,
37+
f"Unable to get signed url HTTP_{r.status_code}. Correlation ID: {correlation_id} - {r.text}",
38+
)
39+
else:
40+
print(
41+
f"Error getting signed URL for {name}: Correlation ID: {correlation_id} HTTP_{r.status_code} - {r.text}",
42+
flush=True,
43+
)
44+
print(f"Retrying in {x} seconds", flush=True)
45+
sleep(x)
46+
47+
# Upload the file to the signed URL with backoff/retry logic
48+
url = r.headers["location"]
49+
path = os.path.join(base, name)
50+
for x in (1, 2, 3, 0):
51+
r = requests.put(
52+
url,
53+
data=open(path, "rb"),
54+
headers={"Content-type": "application/octet-stream"},
55+
)
56+
if not r.ok:
57+
if not x:
58+
return (
59+
name,
60+
f"Unable to upload content HTTP_{r.status_code} - {r.text}",
61+
)
62+
else:
63+
print(
64+
f"Unable to upload content for {name}: HTTP_{r.status_code} - {r.text}"
65+
)
66+
print(f"Retrying in {x} seconds")
67+
sleep(x)
68+
69+
return name, None
70+
except Exception as e:
71+
return name, str(e)
72+
73+
74+
def get_files_to_publish(path: str) -> List[str]:
75+
paths = []
76+
for root, dirs, files in os.walk(path):
77+
for file in files:
78+
paths.append(os.path.join(root, file)[len(path) :])
79+
return paths
80+
81+
82+
def main(num_threads: int, artifacts_dir: str, base_url: str):
83+
paths = get_files_to_publish(artifacts_dir)
84+
print(f"= Found {len(paths)} files to publish", flush=True)
85+
86+
failed = False
87+
work = [(f"{base_url}{x}", artifacts_dir, x) for x in paths]
88+
with Pool(num_threads) as p:
89+
results = p.imap_unordered(upload_file, work)
90+
for i, res in enumerate(results):
91+
name, err = res
92+
print(f"= {i+1} of {len(work)} - {name}", flush=True)
93+
if err:
94+
print(f"|-> ERROR: {err}", flush=True)
95+
failed = True
96+
97+
if failed:
98+
sys.exit(1)
99+
100+
101+
if __name__ == "__main__":
102+
BUILD_DIR = os.environ["BUILD_DIR"]
103+
if BUILD_DIR[-1] != "/":
104+
BUILD_DIR = BUILD_DIR + "/"
105+
106+
URL = os.environ["URL"]
107+
if URL[-1] != "/":
108+
URL = URL + "/"
109+
110+
num_threads = int(num_threads_str)
111+
main(num_threads, BUILD_DIR, URL)

.github/workflows/u-boot.yml

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88
# permissions to none
99
permissions:
1010
contents: read
11+
security-events: read # This is required to handle authentication to our artifact publishing API
1112

1213
env:
1314
# where results will be posted/hosted
@@ -30,7 +31,6 @@ jobs:
3031
container:
3132
image: debian:trixie
3233
volumes:
33-
- /srv/gh-runners/quic-yocto/builds:/fileserver-builds
3434
- /srv/gh-runners/quic-yocto/downloads:/fileserver-downloads
3535
steps:
3636
- uses: actions/checkout@v4
@@ -55,25 +55,25 @@ jobs:
5555
scripts/build-u-boot-rb1.sh
5656
5757
- name: Upload results to fileserver
58+
env:
59+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5860
run: |
5961
set -ux
60-
# curl will be used to talk to fileserver; should be installed by
61-
# default
62-
apt -y install curl
63-
for dir in "/fileserver-builds/${BUILD_ID}" \
64-
"/fileserver-downloads/qcom-deb-images/u-boot-rb1-latest"; do
65-
mkdir -vp "${dir}"
66-
cp -av \
67-
u-boot/u-boot-nodtb.bin.gz \
68-
u-boot/dts/upstream/src/arm64/qcom/qrb2210-rb1.dtb \
69-
u-boot/u-boot-nodtb.bin.gz-dtb \
70-
u-boot/u-boot.bin \
71-
u-boot/rb1-boot.img \
72-
"${dir}"
73-
done
62+
# python3-requests is used by publish_aritfacts.py
63+
apt -y install python3-requests
64+
65+
export BUILD_DIR="/fileserver-downloads/qcom-deb-images/u-boot-rb1-latest"
66+
mkdir -vp ${BUILD_DIR}
67+
cp -av \
68+
u-boot/u-boot-nodtb.bin.gz \
69+
u-boot/dts/upstream/src/arm64/qcom/qrb2210-rb1.dtb \
70+
u-boot/u-boot-nodtb.bin.gz-dtb \
71+
u-boot/u-boot.bin \
72+
u-boot/rb1-boot.img \
73+
${BUILD_DIR}
7474
# perhaps help NFS sync
7575
sync
7676
# instruct fileserver to publish this directory
77-
url="${FILESERVER_URL}/${BUILD_ID}/"
78-
curl -X POST -H 'Accept: text/event-stream' "${url}"
79-
77+
export URL="${FILESERVER_URL}/${BUILD_ID}/"
78+
.github/workflows/publish_artifacts.py
79+
echo Image available at: ${URL}

0 commit comments

Comments
 (0)