Skip to content

Commit 8f3a6f4

Browse files
chore: add internal release workflow for publishing to artifactory (#47)
1 parent 984574d commit 8f3a6f4

3 files changed

Lines changed: 176 additions & 4 deletions

File tree

.github/workflows/checks.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ env:
1414
jobs:
1515
checks:
1616
name: Code Quality Checks
17-
runs-on: ubuntu-latest
17+
runs-on: ${{ vars.RUNNER && fromJSON(vars.RUNNER) || 'ubuntu-latest' }}
1818
permissions:
1919
contents: read
2020
steps:
2121
- name: "Checkout PR Code"
2222
uses: actions/checkout@v4
2323

2424
- name: "Install uv"
25-
uses: astral-sh/setup-uv@v4
25+
uses: astral-sh/setup-uv@v3
2626
with:
2727
version: "latest"
2828
enable-cache: true
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
name: Publish Package to Internal Artifactory
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
types: [opened, synchronize, reopened]
8+
9+
jobs:
10+
publish:
11+
name: Publish to Artifactory
12+
runs-on: ${{ vars.RUNNER && fromJSON(vars.RUNNER) || 'ubuntu-latest' }}
13+
environment: 'artifactory:sap-cloud-sdk'
14+
if: ${{ !contains(github.server_url, 'github.com') }}
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v4
21+
with:
22+
python-version: "3.11"
23+
24+
- name: Install uv
25+
uses: astral-sh/setup-uv@v3
26+
with:
27+
enable-cache: true
28+
29+
- name: Read package name and version from pyproject.toml
30+
id: metadata
31+
run: |
32+
pip install toml
33+
PKG_NAME=$(python -c "import toml; print(toml.load('pyproject.toml')['project']['name'])")
34+
BASE_VERSION=$(python -c "import toml; print(toml.load('pyproject.toml')['project']['version'])")
35+
36+
echo "Base version: $BASE_VERSION"
37+
echo "name=$PKG_NAME" >> $GITHUB_OUTPUT
38+
echo "base_version=$BASE_VERSION" >> $GITHUB_OUTPUT
39+
40+
- name: Generate prerelease version
41+
id: prerelease
42+
run: |
43+
BASE_VERSION="${{ steps.metadata.outputs.base_version }}"
44+
45+
# Get current date in YYYYMMDD format
46+
DATE=$(date +%Y%m%d)
47+
48+
# Get branch name and sanitize it (remove refs/heads/ prefix and replace / with -)
49+
BRANCH_NAME="${{ github.head_ref || github.ref_name }}"
50+
BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/refs\/heads\///' | sed 's/\//-/g')
51+
52+
# Get short commit SHA
53+
SHORT_SHA="${{ github.event.pull_request.head.sha || github.sha }}"
54+
SHORT_SHA=${SHORT_SHA:0:7}
55+
56+
# Create PEP 440-compliant prerelease version
57+
# Format: X.Y.Z.devYYYYMMDD+branch.sha
58+
PRERELEASE_VERSION="${BASE_VERSION}.dev${DATE}+${BRANCH_NAME}.${SHORT_SHA}"
59+
60+
echo "Generated prerelease version: $PRERELEASE_VERSION"
61+
echo "version=$PRERELEASE_VERSION" >> $GITHUB_OUTPUT
62+
63+
- name: Update version in pyproject.toml
64+
run: |
65+
PRERELEASE_VERSION="${{ steps.prerelease.outputs.version }}"
66+
67+
# Update version in pyproject.toml
68+
python -c "
69+
import toml
70+
data = toml.load('pyproject.toml')
71+
data['project']['version'] = '$PRERELEASE_VERSION'
72+
with open('pyproject.toml', 'w') as f:
73+
toml.dump(data, f)
74+
"
75+
76+
echo "Updated pyproject.toml with version: $PRERELEASE_VERSION"
77+
78+
- name: Check if version already exists in Artifactory
79+
env:
80+
REPOSITORY_NAME: ${{ vars.REPOSITORY_NAME }}
81+
ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }}
82+
ARTIFACTORY_USER: ${{ secrets.ARTIFACTORY_USER }}
83+
ARTIFACTORY_TOKEN: ${{ secrets.ARTIFACTORY_TOKEN }}
84+
run: |
85+
PKG_NAME="${{ steps.metadata.outputs.name }}"
86+
VERSION="${{ steps.prerelease.outputs.version }}"
87+
88+
echo "Checking if $PKG_NAME version $VERSION exists in Artifactory..."
89+
90+
# Convert package name to filename format (replace hyphens with underscores)
91+
PKG_FILE_NAME=$(echo "$PKG_NAME" | sed 's/-/_/g')
92+
FILE_PATH="$ARTIFACTORY_URL/$REPOSITORY_NAME/$PKG_NAME/$VERSION/${PKG_FILE_NAME}-${VERSION}.tar.gz"
93+
94+
echo "Checking for file: $FILE_PATH"
95+
96+
# Check if file exists using HEAD request
97+
HTTP_STATUS=$(curl -I -s -o /dev/null -w "%{http_code}" \
98+
-u "$ARTIFACTORY_USER:$ARTIFACTORY_TOKEN" \
99+
"$FILE_PATH")
100+
101+
if [ "$HTTP_STATUS" = "200" ]; then
102+
echo "ERROR: Version $VERSION of $PKG_NAME already exists in Artifactory!"
103+
echo "File found: $FILE_PATH"
104+
echo "Please increment the version in pyproject.toml before publishing."
105+
exit 1
106+
else
107+
echo "Version $VERSION is available for upload to Artifactory"
108+
fi
109+
110+
- name: Build release distribution
111+
run: uv build
112+
113+
- name: Publish to Artifactory
114+
env:
115+
REPOSITORY_NAME: ${{ vars.REPOSITORY_NAME }}
116+
ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }}
117+
ARTIFACTORY_USER: ${{ secrets.ARTIFACTORY_USER }}
118+
ARTIFACTORY_TOKEN: ${{ secrets.ARTIFACTORY_TOKEN }}
119+
run: |
120+
PKG_NAME="${{ steps.metadata.outputs.name }}"
121+
VERSION="${{ steps.prerelease.outputs.version }}"
122+
123+
echo "Publishing to Artifactory..."
124+
echo "Repository URL: $ARTIFACTORY_URL/api/pypi/$REPOSITORY_NAME/"
125+
126+
uv publish \
127+
--publish-url "$ARTIFACTORY_URL/api/pypi/$REPOSITORY_NAME/" \
128+
--username "$ARTIFACTORY_USER" \
129+
--password "$ARTIFACTORY_TOKEN" \
130+
dist/*
131+
132+
echo "Successfully published $PKG_NAME version $VERSION to Artifactory!"
133+
134+
- name: Generate Installation Summary
135+
if: success()
136+
env:
137+
REPOSITORY_NAME: ${{ vars.REPOSITORY_NAME }}
138+
ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }}
139+
run: |
140+
PKG_NAME="${{ steps.metadata.outputs.name }}"
141+
VERSION="${{ steps.prerelease.outputs.version }}"
142+
BASE_VERSION="${{ steps.metadata.outputs.base_version }}"
143+
144+
# Write to GitHub Step Summary
145+
cat >> $GITHUB_STEP_SUMMARY <<EOF
146+
## ✅ Package Published Successfully
147+
148+
**Package:** \`$PKG_NAME\`
149+
**Version:** \`$VERSION\`
150+
**Base Version:** \`$BASE_VERSION\`
151+
**Repository:** $ARTIFACTORY_URL/artifactory/api/pypi/$REPOSITORY_NAME/
152+
153+
---
154+
155+
## 📦 Installation Instructions
156+
157+
\`\`\`bash
158+
# uv
159+
uv add $PKG_NAME==$VERSION --index $ARTIFACTORY_URL/artifactory/api/pypi/$REPOSITORY_NAME/simple/
160+
161+
# Poetry
162+
poetry add $PKG_NAME==$VERSION --source $ARTIFACTORY_URL/artifactory/api/pypi/$REPOSITORY_NAME/simple/
163+
164+
# Pip
165+
pip install $PKG_NAME==$VERSION --index-url $ARTIFACTORY_URL/artifactory/api/pypi/$REPOSITORY_NAME/simple/
166+
\`\`\`
167+
168+
---
169+
170+
*Published at: $(date -u '+%Y-%m-%d %H:%M:%S UTC')*
171+
EOF

.github/workflows/test.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ env:
1818
jobs:
1919
test:
2020
name: Unit Tests with Coverage
21-
runs-on: ubuntu-latest
21+
runs-on: ${{ vars.RUNNER && fromJSON(vars.RUNNER) || 'ubuntu-latest' }}
2222
steps:
2323
- name: "Checkout Repository"
2424
uses: actions/checkout@v4
2525

2626
- name: "Install uv"
27-
uses: astral-sh/setup-uv@v4
27+
uses: astral-sh/setup-uv@v3
2828
with:
2929
version: "latest"
3030
enable-cache: true
@@ -39,6 +39,7 @@ jobs:
3939

4040
- name: "Upload Coverage Report"
4141
uses: actions/upload-artifact@v4
42+
if: contains(github.server_url, 'github.com')
4243
with:
4344
name: coverage-report
4445
path: |

0 commit comments

Comments
 (0)