Gitea: Create release pipeline
This commit is contained in:
@@ -8,10 +8,17 @@ on:
|
||||
- '**'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
create_release:
|
||||
type: boolean
|
||||
description: 'Create release'
|
||||
required: false
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build-rpm:
|
||||
name: build:rpm (${{ matrix.distro }})
|
||||
if: github.ref_type != 'workflow_dispatch'
|
||||
runs-on: ${{ matrix.runner }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -88,8 +95,19 @@ jobs:
|
||||
fi
|
||||
for file in "${files[@]}"; do
|
||||
echo "Uploading $file -> ${{ matrix.upload_url }}"
|
||||
curl --fail --user __token__:"$TOKEN" --upload-file "$file" "${{ matrix.upload_url }}"
|
||||
curl --fail --user __token__:"$TOKEN" --upload-file "$file" "${{ matrix.upload_url }}"
|
||||
python gitea_upload_file.py
|
||||
done
|
||||
|
||||
if [ "${{ matrix.distro }}" = "rocky8_nocuda" ]; then
|
||||
for file in jfjoch-viewer*.rpm; do
|
||||
python gitea_upload_file.py "$file"
|
||||
done
|
||||
elif [ "${{ matrix.distro }}" = "ubuntu2204_nocuda" ]; then
|
||||
for file in jfjoch*viewer*.deb; do
|
||||
python gitea_upload_file.py "$file"
|
||||
done
|
||||
fi
|
||||
python-client:
|
||||
name: Generate python client
|
||||
runs-on: jfjoch_rocky8
|
||||
@@ -103,7 +121,6 @@ jobs:
|
||||
run: |
|
||||
twine upload -u __token__ -p ${{ secrets.CI_PYPI_TOKEN }} --skip-existing dist/*
|
||||
twine upload -u __token__ -p ${{ secrets.PIP_REPOSITORY_API_TOKEN }} --repository-url https://gitea.psi.ch/api/packages/mx/pypi dist/*
|
||||
|
||||
documentation:
|
||||
name: Build documentation
|
||||
runs-on: jfjoch_rocky8
|
||||
@@ -133,6 +150,7 @@ jobs:
|
||||
unit-tests:
|
||||
name: Unit tests
|
||||
runs-on: jfjoch_rocky8
|
||||
if: github.ref_type != 'tag' && github.ref_type != 'workflow_dispatch'
|
||||
container:
|
||||
image: gitea.psi.ch/leonarski_f/jfjoch_rocky8:2509
|
||||
options: --gpus all
|
||||
@@ -158,3 +176,28 @@ jobs:
|
||||
run: |
|
||||
cd build/tools
|
||||
./jfjoch_hdf5_test ../../tests/test_data/compression_benchmark.h5
|
||||
|
||||
create-release:
|
||||
name: Create release
|
||||
runs-on: jfjoch_rocky8
|
||||
if: github.event_name == 'workflow_dispatch' && (github.event.inputs.create_release == 'true' || github.event.inputs.create_release == true)
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: 'true' # Optional; should be the default
|
||||
- name: Configure auth and fetch LFS
|
||||
shell: bash
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.PIP_REPOSITORY_API_TOKEN }}
|
||||
run: |
|
||||
git lfs install --local
|
||||
AUTH=$(git config --local http.${{ github.server_url }}/.extraheader)
|
||||
git config --local --unset http.${{ github.server_url }}/.extraheader
|
||||
git config --local http.${{ github.server_url }}/${{ github.repository }}.git/info/lfs/objects/batch.extraheader "$AUTH"
|
||||
git lfs pull
|
||||
- name: Create release
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.PIP_REPOSITORY_API_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 gitea_create_release.py
|
||||
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import Optional
|
||||
try:
|
||||
import requests
|
||||
except ModuleNotFoundError:
|
||||
print("ERROR: Python 'requests' package is required. Please install it (e.g., pip install requests).")
|
||||
sys.exit(1)
|
||||
|
||||
gitea_api_url = "https://gitea.psi.ch/api/v1/"
|
||||
repo_owner = "mx"
|
||||
repo_name = "jungfraujoch"
|
||||
|
||||
gitea_token = os.getenv('GITEA_TOKEN')
|
||||
if gitea_token is None:
|
||||
print("ERROR: Required environment variables not set")
|
||||
sys.exit(1)
|
||||
|
||||
def read_version():
|
||||
try:
|
||||
with open('VERSION', 'r') as f:
|
||||
return f.readline().strip()
|
||||
except FileNotFoundError:
|
||||
print("ERROR: VERSION file not found")
|
||||
sys.exit(1)
|
||||
|
||||
def create_release(version):
|
||||
headers = {
|
||||
'Authorization': f'token {gitea_token}',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
data = {
|
||||
'tag_name': version,
|
||||
'name': f'Release {version}',
|
||||
'draft': False,
|
||||
'prerelease': '-rc.' in version or '-alpha.' in version or '-beta.' in version
|
||||
}
|
||||
|
||||
url = f'{gitea_api_url}/repos/{repo_owner}/{repo_name}/releases'
|
||||
|
||||
response = requests.post(url, headers=headers, json=data)
|
||||
if response.status_code != 201:
|
||||
print(f"ERROR: Failed to create release. Status code: {response.status_code}")
|
||||
print(response.text)
|
||||
sys.exit(1)
|
||||
|
||||
release = response.json()
|
||||
print(f"Successfully created release {version}")
|
||||
return release
|
||||
|
||||
def get_release_by_tag(version: str):
|
||||
"""
|
||||
Fetch release information by tag name.
|
||||
Returns the release object (dict) or exits on error.
|
||||
"""
|
||||
headers = {
|
||||
'Authorization': f'token {gitea_token}',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
url = f'{gitea_api_url}/repos/{repo_owner}/{repo_name}/releases/tags/{version}'
|
||||
resp = requests.get(url, headers=headers)
|
||||
if resp.status_code != 200:
|
||||
print(f"ERROR: Failed to fetch release {version}. Status code: {resp.status_code}")
|
||||
print(resp.text)
|
||||
sys.exit(1)
|
||||
return resp.json()
|
||||
|
||||
def upload_file_to_release(version: str, file_path: str, name: Optional[str] = None, label: Optional[str] = None):
|
||||
"""
|
||||
Upload a file as an asset to the release identified by the given version tag.
|
||||
|
||||
:param version: Tag name of the release (e.g., '1.2.3' or '1.2.3-rc.1')
|
||||
:param file_path: Local file path to upload
|
||||
:param name: Optional asset name to display in release (defaults to filename)
|
||||
:param label: Optional asset label (display name)
|
||||
"""
|
||||
if not os.path.isfile(file_path):
|
||||
print(f"ERROR: File not found: {file_path}")
|
||||
sys.exit(1)
|
||||
|
||||
# Ensure the release exists and get its ID
|
||||
release = get_release_by_tag(version)
|
||||
release_id = release.get('id')
|
||||
if release_id is None:
|
||||
print("ERROR: Release ID not found in response")
|
||||
sys.exit(1)
|
||||
|
||||
headers = {
|
||||
'Authorization': f'token {gitea_token}',
|
||||
}
|
||||
|
||||
asset_name = name if name else os.path.basename(file_path)
|
||||
data = {'name': asset_name}
|
||||
if label:
|
||||
data['label'] = label
|
||||
|
||||
url = f'{gitea_api_url}/repos/{repo_owner}/{repo_name}/releases/{release_id}/assets'
|
||||
|
||||
with open(file_path, 'rb') as f:
|
||||
files = {
|
||||
'attachment': (asset_name, f, 'application/octet-stream'),
|
||||
}
|
||||
resp = requests.post(url, headers=headers, data=data, files=files)
|
||||
|
||||
if resp.status_code not in (201, 200):
|
||||
print(f"ERROR: Failed to upload asset. Status code: {resp.status_code}")
|
||||
print(resp.text)
|
||||
sys.exit(1)
|
||||
|
||||
asset = resp.json()
|
||||
browser_download_url = asset.get('browser_download_url') or asset.get('browser_url') or asset.get('url')
|
||||
print(f"Uploaded asset '{asset_name}' to release {version}: {browser_download_url}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
version = read_version()
|
||||
release = create_release(version)
|
||||
|
||||
upload_file_to_release(version, 'fpga/images/jfjoch_fpga_pcie_8x10g.mcs.gz', 'jfjoch_fpga_pcie_8x10g.mcs.gz', '8x10G FPGA image')
|
||||
upload_file_to_release(version, 'fpga/images/jfjoch_fpga_pcie_100g.mcs.gz', 'jfjoch_fpga_pcie_100g.mcs.gz', '100G FPGA image')
|
||||
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import Optional
|
||||
try:
|
||||
import requests
|
||||
except ModuleNotFoundError:
|
||||
print("ERROR: Python 'requests' package is required. Please install it (e.g., pip install requests).")
|
||||
sys.exit(1)
|
||||
|
||||
gitea_api_url = "https://gitea.psi.ch/api/v1/"
|
||||
repo_owner = "mx"
|
||||
repo_name = "jungfraujoch"
|
||||
|
||||
gitea_token = os.getenv('GITEA_TOKEN')
|
||||
if gitea_token is None:
|
||||
print("ERROR: Required environment variables not set")
|
||||
sys.exit(1)
|
||||
|
||||
def read_version():
|
||||
try:
|
||||
with open('VERSION', 'r') as f:
|
||||
return f.readline().strip()
|
||||
except FileNotFoundError:
|
||||
print("ERROR: VERSION file not found")
|
||||
sys.exit(1)
|
||||
|
||||
def create_release(version):
|
||||
headers = {
|
||||
'Authorization': f'token {gitea_token}',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
data = {
|
||||
'tag_name': version,
|
||||
'name': f'Release {version}',
|
||||
'draft': False,
|
||||
'prerelease': '-rc.' in version or '-alpha.' in version or '-beta.' in version
|
||||
}
|
||||
|
||||
url = f'{gitea_api_url}/repos/{repo_owner}/{repo_name}/releases'
|
||||
|
||||
response = requests.post(url, headers=headers, json=data)
|
||||
if response.status_code != 201:
|
||||
print(f"ERROR: Failed to create release. Status code: {response.status_code}")
|
||||
print(response.text)
|
||||
sys.exit(1)
|
||||
|
||||
release = response.json()
|
||||
print(f"Successfully created release {version}")
|
||||
return release
|
||||
|
||||
def get_release_by_tag(version: str):
|
||||
"""
|
||||
Fetch release information by tag name.
|
||||
Returns the release object (dict) or exits on error.
|
||||
"""
|
||||
headers = {
|
||||
'Authorization': f'token {gitea_token}',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
url = f'{gitea_api_url}/repos/{repo_owner}/{repo_name}/releases/tags/{version}'
|
||||
resp = requests.get(url, headers=headers)
|
||||
if resp.status_code != 200:
|
||||
print(f"ERROR: Failed to fetch release {version}. Status code: {resp.status_code}")
|
||||
print(resp.text)
|
||||
sys.exit(1)
|
||||
return resp.json()
|
||||
|
||||
def upload_file_to_release(version: str, file_path: str, name: Optional[str] = None, label: Optional[str] = None):
|
||||
"""
|
||||
Upload a file as an asset to the release identified by the given version tag.
|
||||
|
||||
:param version: Tag name of the release (e.g., '1.2.3' or '1.2.3-rc.1')
|
||||
:param file_path: Local file path to upload
|
||||
:param name: Optional asset name to display in release (defaults to filename)
|
||||
:param label: Optional asset label (display name)
|
||||
"""
|
||||
if not os.path.isfile(file_path):
|
||||
print(f"ERROR: File not found: {file_path}")
|
||||
sys.exit(1)
|
||||
|
||||
asset_name = name if name else os.path.basename(file_path)
|
||||
print(f"Uploading file '{file_path}' to release {version} as {asset_name}")
|
||||
|
||||
# Ensure the release exists and get its ID
|
||||
release = get_release_by_tag(version)
|
||||
release_id = release.get('id')
|
||||
if release_id is None:
|
||||
print("ERROR: Release ID not found in response")
|
||||
sys.exit(1)
|
||||
|
||||
headers = {
|
||||
'Authorization': f'token {gitea_token}',
|
||||
}
|
||||
|
||||
data = {'name': asset_name}
|
||||
if label:
|
||||
data['label'] = label
|
||||
|
||||
url = f'{gitea_api_url}/repos/{repo_owner}/{repo_name}/releases/{release_id}/assets'
|
||||
|
||||
with open(file_path, 'rb') as f:
|
||||
files = {
|
||||
'attachment': (asset_name, f, 'application/octet-stream'),
|
||||
}
|
||||
resp = requests.post(url, headers=headers, data=data, files=files)
|
||||
|
||||
if resp.status_code not in (201, 200):
|
||||
print(f"ERROR: Failed to upload asset. Status code: {resp.status_code}")
|
||||
print(resp.text)
|
||||
sys.exit(1)
|
||||
|
||||
asset = resp.json()
|
||||
browser_download_url = asset.get('browser_download_url') or asset.get('browser_url') or asset.get('url')
|
||||
print(f"Uploaded asset '{asset_name}' to release {version}: {browser_download_url}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
version = read_version()
|
||||
if len(sys.argv) != 2:
|
||||
exit(1)
|
||||
|
||||
upload_file_to_release(version, sys.argv[1])
|
||||
|
||||
Reference in New Issue
Block a user