From da387f2ee602390d616c79bf4057ccf941e21462 Mon Sep 17 00:00:00 2001 From: "Max P." Date: Wed, 16 Jul 2025 11:41:35 +0200 Subject: [PATCH] feat(ci): add workflows for nightly builds and releases - Introduce separate workflows for nightly and release builds - Add scripts for version management, asset uploads, and cleanup - Improve Python environment setup and dependency caching --- .../default_merge_message/MERGE_TEMPLATE.md | 5 ++ .gitea/scripts/cleanup_versions.sh | 45 +++++++++++++ .gitea/scripts/get-release-id.sh | 21 ++++++ .gitea/scripts/set_poetry_version.sh | 14 ++++ .gitea/scripts/sync_version_from_poetry.sh | 21 ++++++ .gitea/scripts/upload-asset.sh | 40 ++++++++++++ .../workflows/build-and-deploy-nightly.yml | 37 +++++++---- .gitea/workflows/build-and-deploy-release.yml | 64 +++++++++++++++++++ .gitea/workflows/release.yml | 18 ++++++ 9 files changed, 253 insertions(+), 12 deletions(-) create mode 100644 .gitea/default_merge_message/MERGE_TEMPLATE.md create mode 100755 .gitea/scripts/cleanup_versions.sh create mode 100755 .gitea/scripts/get-release-id.sh create mode 100755 .gitea/scripts/set_poetry_version.sh create mode 100755 .gitea/scripts/sync_version_from_poetry.sh create mode 100755 .gitea/scripts/upload-asset.sh rename .github/workflows/build-and-deploy.yml => .gitea/workflows/build-and-deploy-nightly.yml (52%) create mode 100644 .gitea/workflows/build-and-deploy-release.yml create mode 100644 .gitea/workflows/release.yml diff --git a/.gitea/default_merge_message/MERGE_TEMPLATE.md b/.gitea/default_merge_message/MERGE_TEMPLATE.md new file mode 100644 index 0000000..0d9c4f1 --- /dev/null +++ b/.gitea/default_merge_message/MERGE_TEMPLATE.md @@ -0,0 +1,5 @@ +chore(pr): ${PullRequestTitle} ${PullRequestReference} + +${PullRequestDescription} + +Merged from ${HeadBranch} into ${BaseBranch} diff --git a/.gitea/scripts/cleanup_versions.sh b/.gitea/scripts/cleanup_versions.sh new file mode 100755 index 0000000..c8c23bc --- /dev/null +++ b/.gitea/scripts/cleanup_versions.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -euo pipefail + +# cleanup_dev_versions.sh - Delete old PyPI dev versions from Gitea package registry + +# Required environment variables +USERNAME="${TWINE_USERNAME}" +TOKEN="${TWINE_PASSWORD}" +REPO="${GITHUB_REPOSITORY}" # e.g., maxp/repocat +API_BASE="${GITHUB_API_URL%/}" # Strip trailing slash if present + +OWNER="${REPO%%/*}" +PACKAGE_NAME="${REPO##*/}" +API_URL="${API_BASE}/packages/${OWNER}/pypi/${PACKAGE_NAME}" + +# Fetch the list of versions +response=$(curl -s -u "$USERNAME:$TOKEN" "$API_URL") + +# Extract all .dev versions, sort by creation time +mapfile -t versions_to_delete < <(echo "$response" | jq -r ' + map(select(.version | test("\\.dev"))) | + sort_by(.created_at) | + .[0:-1][] | + .version') + +# Determine latest version to keep +latest_version=$(echo "$response" | jq -r ' + map(select(.version | test("\\.dev"))) | + sort_by(.created_at) | + last.version') + +if [[ -z "$latest_version" || ${#versions_to_delete[@]} -eq 0 ]]; then + echo "No old .dev versions to delete." + exit 0 +fi + +echo "Keeping latest .dev version: $latest_version" + +# Delete old .dev versions +for version in "${versions_to_delete[@]}"; do + echo "Deleting old .dev version: $version" + curl -s -X DELETE -u "$USERNAME:$TOKEN" "$API_URL/$version" +done + +echo "Cleanup complete." \ No newline at end of file diff --git a/.gitea/scripts/get-release-id.sh b/.gitea/scripts/get-release-id.sh new file mode 100755 index 0000000..1058ede --- /dev/null +++ b/.gitea/scripts/get-release-id.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Eingaben +TAG="$1" +TOKEN="${ACTIONS_RUNTIME_TOKEN:-}" +REPO="${GITHUB_REPOSITORY:-owner/example}" +API="${GITHUB_API_URL:-https://gitea.example.tld/api/v1}" + +OWNER=$(echo "$REPO" | cut -d/ -f1) +NAME=$(echo "$REPO" | cut -d/ -f2) + +RESPONSE=$(curl -sf \ + -H "Authorization: token $TOKEN" \ + "$API/repos/$OWNER/$NAME/releases/tags/$TAG") + +RELEASE_ID=$(echo "$RESPONSE" | jq -r '.id') +echo "Release-ID für $TAG ist: $RELEASE_ID" + +# Für GitHub Actions als Umgebungsvariable +echo "GT_RELEASE_ID=$RELEASE_ID" >> "$GITHUB_ENV" diff --git a/.gitea/scripts/set_poetry_version.sh b/.gitea/scripts/set_poetry_version.sh new file mode 100755 index 0000000..272e938 --- /dev/null +++ b/.gitea/scripts/set_poetry_version.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +BASE_VERSION=$(cat VERSION) +NIGHTLY_SUFFIX="" + +if [[ "$1" == "nightly" ]]; then + # Beispiel: 20240511.1358 → 11. Mai, 13:58 Uhr + NIGHTLY_SUFFIX=".dev$(date +%Y%m%d%H%M)" +fi + +FULL_VERSION="${BASE_VERSION}${NIGHTLY_SUFFIX}" + +echo "Using version: $FULL_VERSION" +poetry version "$FULL_VERSION" diff --git a/.gitea/scripts/sync_version_from_poetry.sh b/.gitea/scripts/sync_version_from_poetry.sh new file mode 100755 index 0000000..a236c0f --- /dev/null +++ b/.gitea/scripts/sync_version_from_poetry.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Stelle sicher, dass wir im Projektverzeichnis sind +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "$ROOT_DIR" + +PYPROJECT="pyproject.toml" +VERSION_FILE="VERSION" + +# Extrahiere die Version mit grep + sed (keine externen Abhängigkeiten nötig) +VERSION=$(grep -E '^version\s*=' "$PYPROJECT" | head -n1 | sed -E 's/.*=\s*"([^"]+)".*/\1/') + +if [[ -z "$VERSION" ]]; then + echo "❌ Version konnte nicht aus $PYPROJECT gelesen werden." + exit 1 +fi + +printf "%s" "$VERSION" > "$VERSION_FILE" +echo "✅ Version synchronisiert: $VERSION → $VERSION_FILE" diff --git a/.gitea/scripts/upload-asset.sh b/.gitea/scripts/upload-asset.sh new file mode 100755 index 0000000..36f5e73 --- /dev/null +++ b/.gitea/scripts/upload-asset.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Eingabeparameter +FILE_PATH="$1" # z. B. ./dist/build.zip +CUSTOM_NAME="${2:-}" # optional: anderer Name unter dem das Asset gespeichert werden soll +RELEASE_ID="${GT_RELEASE_ID:-}" # aus Umgebung + +# Validierung +if [[ -z "$RELEASE_ID" ]]; then + echo "❌ RELEASE_ID ist nicht gesetzt. Abbruch." + exit 1 +fi + +if [[ ! -f "$FILE_PATH" ]]; then + echo "❌ Datei '$FILE_PATH' existiert nicht. Abbruch." + exit 1 +fi + +# Default-Konfiguration +TOKEN="${ACTIONS_RUNTIME_TOKEN:-}" +REPO="${GITHUB_REPOSITORY:-owner/example}" +API="${GITHUB_API_URL:-https://gitea.example.tld/api/v1}" + +# Owner/Repo auflösen +OWNER=$(echo "$REPO" | cut -d/ -f1) +NAME=$(echo "$REPO" | cut -d/ -f2) + +# Dateiname setzen +FILENAME="${CUSTOM_NAME:-$(basename "$FILE_PATH")}" + +echo "🔼 Uploading '$FILE_PATH' as '$FILENAME' to release ID $RELEASE_ID" + +# Upload +curl -sf -X POST \ + -H "Authorization: token $TOKEN" \ + -F "attachment=@$FILE_PATH" \ + "$API/repos/$OWNER/$NAME/releases/$RELEASE_ID/assets?name=$FILENAME" + +echo "✅ Upload abgeschlossen: $FILENAME" diff --git a/.github/workflows/build-and-deploy.yml b/.gitea/workflows/build-and-deploy-nightly.yml similarity index 52% rename from .github/workflows/build-and-deploy.yml rename to .gitea/workflows/build-and-deploy-nightly.yml index f8b176a..be10cfd 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.gitea/workflows/build-and-deploy-nightly.yml @@ -1,30 +1,33 @@ -# .gitea/workflows/publish.yml - -name: Build and Publish +name: Build and Publish nightly package on: + workflow_dispatch: push: - paths: - - "pyproject.toml" # Nur bei Änderungen an dieser Datei - workflow_dispatch: # Manuelles Anstoßen zulassen + branches: + - main + paths-ignore: + - 'CHANGELOG.md' jobs: build-and-publish: runs-on: ubuntu-22.04 steps: - - name: ⚙️ Prepare Environment Variables - run: | - echo "AGENT_TOOLSDIRECTORY=/home/runner/toolcache" >> $GITHUB_ENV - mkdir -p /home/runner/toolcache - - name: Checkout Repository uses: actions/checkout@v4 - name: 🐍 Setup Python uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.12" + + - name: 🔄 Restore cache + uses: https://git.0xmax42.io/actions/cache@v1 + with: + key: poetry-v1-${{ runner.os }}-${{ hashFiles('poetry.lock') }} + paths: | + ~/.cache/pypoetry + ~/.cache/pip - name: Install Poetry run: | @@ -35,6 +38,9 @@ jobs: run: | poetry install + - name: Set version from VERSION file (with nightly suffix) + run: ./.gitea/scripts/set_poetry_version.sh nightly + - name: Build Package working-directory: . run: | @@ -47,3 +53,10 @@ jobs: TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} run: | poetry run twine upload --repository-url ${{ secrets.TWINE_URL }} dist/* + + - name: Cleanup old dev versions + run: | + .gitea/scripts/cleanup_versions.sh '\.dev' + env: + TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }} + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} \ No newline at end of file diff --git a/.gitea/workflows/build-and-deploy-release.yml b/.gitea/workflows/build-and-deploy-release.yml new file mode 100644 index 0000000..46a6dbf --- /dev/null +++ b/.gitea/workflows/build-and-deploy-release.yml @@ -0,0 +1,64 @@ +name: Build and Publish nightly package + +on: + release: + types: [published] + +jobs: + build-and-publish: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + ref: ${{ github.event.release.tag_name }} + + - name: 🐍 Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: 🔄 Restore cache + uses: https://git.0xmax42.io/actions/cache@v1 + with: + key: poetry-v1-${{ runner.os }}-${{ hashFiles('poetry.lock') }} + paths: | + ~/.cache/pypoetry + ~/.cache/pip + + - name: Install Poetry + run: | + pip install poetry + + - name: Install Project Dependencies + working-directory: . + run: | + poetry install + + - name: Build Package + working-directory: . + run: | + poetry build + + - name: Get built wheel filename + id: get_whl + run: | + echo "whl_file=$(basename dist/*.whl)" >> $GITHUB_OUTPUT + echo "sdist_file=$(basename dist/*.tar.gz)" >> $GITHUB_OUTPUT + + - name: Publish to Gitea Package Registry + working-directory: . + env: + TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }} + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + run: | + poetry run twine upload --repository-url ${{ secrets.TWINE_URL }} dist/* + + - name: Get Release ID from tag + run: .gitea/scripts/get-release-id.sh "${{ github.event.release.tag_name }}" + + - name: Upload assets + run: | + .gitea/scripts/upload-asset.sh ./dist/${{ steps.get_whl.outputs.whl_file }} + .gitea/scripts/upload-asset.sh ./dist/${{ steps.get_whl.outputs.sdist_file }} \ No newline at end of file diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..277e6b5 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,18 @@ +name: Auto Changelog & (Release) + +on: + push: + branches: + - main + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Release + uses: https://git.0xmax42.io/actions/auto-changelog-release-action@v0 + with: + token: ${{ secrets.RELEASE_PUBLISH_TOKEN }}