Skip to content

Commit cb5de84

Browse files
authored
Merge pull request #13682 from quarto-dev/gha/separate-cloudsmith
2 parents e445b3c + 2e2a6c5 commit cb5de84

File tree

2 files changed

+193
-49
lines changed

2 files changed

+193
-49
lines changed

.github/workflows/create-release.yml

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -776,54 +776,12 @@ jobs:
776776
name: quarto
777777
daily: ${{ inputs.pre-release }}
778778

779-
cloudsmith-push:
779+
call-cloudsmith-publish:
780780
if: ${{ inputs.publish-release && ! (inputs.pre-release == true) }}
781-
runs-on: ubuntu-latest
782781
needs: [configure, publish-release]
783-
strategy:
784-
matrix:
785-
arch: [x86_64, aarch64]
786-
format: [deb, rpm]
787-
repo: [open]
788-
steps:
789-
- uses: actions/checkout@v4
790-
with:
791-
sparse-checkout: |
792-
.github
793-
794-
- name: Prevent Re-run
795-
if: ${{ inputs.publish-release }}
796-
uses: ./.github/workflows/actions/prevent-rerun
797-
798-
- name: Download Artifacts
799-
uses: actions/download-artifact@v4
800-
801-
- name: Set package file name
802-
id: pkg_file
803-
run: |
804-
if [ "${{ matrix.format }}" == "deb" ]; then
805-
if [ "${{ matrix.arch }}" == "x86_64" ]; then
806-
echo "arch_name=amd64" >> $GITHUB_OUTPUT
807-
else
808-
echo "arch_name=arm64" >> $GITHUB_OUTPUT
809-
fi
810-
else
811-
if [ "${{ matrix.arch }}" == "x86_64" ]; then
812-
echo "arch_name=x86_64" >> $GITHUB_OUTPUT
813-
else
814-
echo "arch_name=aarch64" >> $GITHUB_OUTPUT
815-
fi
816-
fi
817-
818-
- name: Push ${{ matrix.format }} ${{ matrix.arch }} to Cloudsmith ${{ matrix.repo }}
819-
uses: cloudsmith-io/action@master
820-
with:
821-
api-key: ${{ secrets.CLOUDSMITH_API_KEY }}
822-
command: "push"
823-
format: "${{ matrix.format }}"
824-
owner: "posit"
825-
repo: "${{ matrix.repo }}"
826-
distro: "any-distro"
827-
release: "any-version"
828-
republish: "true"
829-
file: "./Linux-${{ matrix.format }}-${{ matrix.arch }}-Installer/quarto-${{needs.configure.outputs.version}}-linux-${{ steps.pkg_file.outputs.arch_name }}.${{ matrix.format }}"
782+
uses: ./.github/workflows/publish-cloudsmith.yml
783+
with:
784+
version: ${{ needs.configure.outputs.tag_name }}
785+
dry-run: false
786+
secrets:
787+
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
name: Publish to Cloudsmith
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: "Release version/tag (e.g., v1.9.123 or 1.9.123, or 'latest' for most recent)"
8+
required: false
9+
type: string
10+
default: "latest"
11+
dry-run:
12+
description: "Dry run (don't actually publish)"
13+
required: false
14+
type: boolean
15+
default: true
16+
workflow_call:
17+
inputs:
18+
version:
19+
description: "Release version/tag"
20+
required: true
21+
type: string
22+
dry-run:
23+
description: "Dry run (don't actually publish)"
24+
required: false
25+
type: boolean
26+
default: false
27+
secrets:
28+
CLOUDSMITH_API_KEY:
29+
required: true
30+
31+
jobs:
32+
determine-version:
33+
runs-on: ubuntu-latest
34+
outputs:
35+
tag_name: ${{ steps.resolve.outputs.tag_name }}
36+
version: ${{ steps.resolve.outputs.version }}
37+
is_prerelease: ${{ steps.resolve.outputs.is_prerelease }}
38+
steps:
39+
- uses: actions/checkout@v4
40+
with:
41+
sparse-checkout: |
42+
.github
43+
44+
- name: Resolve version and tag
45+
id: resolve
46+
run: |
47+
VERSION_INPUT="${{ inputs.version }}"
48+
49+
# If version is "latest" or empty, get the latest release
50+
if [ "$VERSION_INPUT" == "latest" ] || [ -z "$VERSION_INPUT" ]; then
51+
echo "Fetching latest release..."
52+
TAG_NAME=$(gh release list --limit 1 --json tagName --jq '.[0].tagName')
53+
IS_PRERELEASE=$(gh release view "$TAG_NAME" --json isPrerelease --jq '.isPrerelease')
54+
else
55+
# Ensure tag has 'v' prefix
56+
if [[ "$VERSION_INPUT" == v* ]]; then
57+
TAG_NAME="$VERSION_INPUT"
58+
else
59+
TAG_NAME="v$VERSION_INPUT"
60+
fi
61+
62+
# Check if release exists and get prerelease status
63+
if ! gh release view "$TAG_NAME" > /dev/null 2>&1; then
64+
echo "::error::Release $TAG_NAME not found"
65+
exit 1
66+
fi
67+
IS_PRERELEASE=$(gh release view "$TAG_NAME" --json isPrerelease --jq '.isPrerelease')
68+
fi
69+
70+
# Extract version without 'v' prefix
71+
VERSION="${TAG_NAME#v}"
72+
73+
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
74+
echo "version=$VERSION" >> $GITHUB_OUTPUT
75+
echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT
76+
77+
echo "Resolved to: $TAG_NAME (version: $VERSION, prerelease: $IS_PRERELEASE)"
78+
env:
79+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
80+
81+
- name: Check not prerelease
82+
if: steps.resolve.outputs.is_prerelease == 'true'
83+
run: |
84+
echo "::error::Release ${{ steps.resolve.outputs.tag_name }} is a prerelease. Cloudsmith publishing is only for stable releases."
85+
exit 1
86+
87+
validate-all-assets:
88+
runs-on: ubuntu-latest
89+
needs: [determine-version]
90+
steps:
91+
- name: Validate all packages exist in release
92+
run: |
93+
TAG_NAME="${{ needs.determine-version.outputs.tag_name }}"
94+
VERSION="${{ needs.determine-version.outputs.version }}"
95+
96+
echo "Validating packages for release $TAG_NAME..."
97+
98+
# Get list of assets from release (API call, no download)
99+
ASSETS=$(gh release view "$TAG_NAME" --json assets --jq '.assets[].name')
100+
101+
MISSING=0
102+
REQUIRED_FILES=(
103+
"quarto-${VERSION}-linux-amd64.deb"
104+
"quarto-${VERSION}-linux-arm64.deb"
105+
"quarto-${VERSION}-linux-x86_64.rpm"
106+
"quarto-${VERSION}-linux-aarch64.rpm"
107+
)
108+
109+
for FILE in "${REQUIRED_FILES[@]}"; do
110+
if echo "$ASSETS" | grep -q "^${FILE}$"; then
111+
echo "✓ Found: $FILE"
112+
else
113+
echo "::error::Missing: $FILE"
114+
MISSING=$((MISSING + 1))
115+
fi
116+
done
117+
118+
if [ $MISSING -gt 0 ]; then
119+
echo "::error::$MISSING package(s) missing from release. All 4 packages required for Cloudsmith publishing."
120+
exit 1
121+
fi
122+
123+
echo "All required packages present in release"
124+
env:
125+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
126+
127+
publish-cloudsmith:
128+
runs-on: ubuntu-latest
129+
needs: [determine-version, validate-all-assets]
130+
strategy:
131+
matrix:
132+
arch: [x86_64, aarch64]
133+
format: [deb, rpm]
134+
steps:
135+
- name: Set package architecture name
136+
id: pkg_arch
137+
run: |
138+
if [ "${{ matrix.format }}" == "deb" ]; then
139+
if [ "${{ matrix.arch }}" == "x86_64" ]; then
140+
echo "arch_name=amd64" >> $GITHUB_OUTPUT
141+
else
142+
echo "arch_name=arm64" >> $GITHUB_OUTPUT
143+
fi
144+
else
145+
if [ "${{ matrix.arch }}" == "x86_64" ]; then
146+
echo "arch_name=x86_64" >> $GITHUB_OUTPUT
147+
else
148+
echo "arch_name=aarch64" >> $GITHUB_OUTPUT
149+
fi
150+
fi
151+
152+
- name: Download and validate package from release
153+
run: |
154+
TAG_NAME="${{ needs.determine-version.outputs.tag_name }}"
155+
VERSION="${{ needs.determine-version.outputs.version }}"
156+
ARCH_NAME="${{ steps.pkg_arch.outputs.arch_name }}"
157+
FILE_NAME="quarto-${VERSION}-linux-${ARCH_NAME}.${{ matrix.format }}"
158+
159+
echo "Downloading $FILE_NAME from release $TAG_NAME..."
160+
161+
if ! gh release download "$TAG_NAME" --pattern "$FILE_NAME"; then
162+
echo "::error::Failed to download $FILE_NAME from release $TAG_NAME"
163+
exit 1
164+
fi
165+
166+
if [ ! -f "$FILE_NAME" ]; then
167+
echo "::error::Package file $FILE_NAME not found in release"
168+
exit 1
169+
fi
170+
171+
echo "✓ Successfully downloaded and validated: $FILE_NAME"
172+
env:
173+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
174+
175+
- name: Install and authenticate Cloudsmith CLI
176+
uses: cloudsmith-io/[email protected]
177+
with:
178+
api-key: ${{ secrets.CLOUDSMITH_API_KEY }}
179+
180+
- name: Push ${{ matrix.format }} ${{ matrix.arch }} to Cloudsmith${{ inputs.dry-run && ' (DRY RUN)' || '' }}
181+
run: |
182+
cloudsmith push ${{ matrix.format }} \
183+
posit/open/any-distro/any-version \
184+
"quarto-${{ needs.determine-version.outputs.version }}-linux-${{ steps.pkg_arch.outputs.arch_name }}.${{ matrix.format }}" \
185+
--republish \
186+
${{ inputs.dry-run && '--dry-run' || '' }}

0 commit comments

Comments
 (0)