From b7d82bf07a5830a20c1ce0457e2a5895860de367 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Tue, 18 Nov 2025 23:38:35 +0200 Subject: [PATCH 1/6] ci: refactor workflows with extended naming support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adopt improved workflow structure from cockpit-apt: - Replace build.yml with pr.yml (runs tests on PRs) - Replace release-drafter.yml with main.yml (tests + build + releases) - Update release.yml with APT_DISTRO/APT_COMPONENT env vars - Create composite actions (.github/actions/run-tests, build-deb) - Add helper scripts (read-version.sh, check-release-exists.sh, generate-release-notes.sh) Key changes: - Eliminate parallel builds (reduce CI time ~50%) - Clear separation of concerns (pr.yml, main.yml, release.yml) - Extended naming support: packages renamed with +any+haltabs suffix - Version read from VERSION file - Build uses arm64 runners for package building Closes #32 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/actions/build-deb/action.yml | 23 ++++ .github/actions/run-tests/action.yml | 17 +++ .github/scripts/check-release-exists.sh | 79 +++++++++++ .github/scripts/generate-release-notes.sh | 135 ++++++++++++++++++ .github/scripts/read-version.sh | 13 ++ .github/workflows/build.yml | 33 ----- .github/workflows/main.yml | 158 ++++++++++++++++++++++ .github/workflows/pr.yml | 19 +++ .github/workflows/release-drafter.yml | 16 --- .github/workflows/release.yml | 64 +++------ 10 files changed, 464 insertions(+), 93 deletions(-) create mode 100644 .github/actions/build-deb/action.yml create mode 100644 .github/actions/run-tests/action.yml create mode 100755 .github/scripts/check-release-exists.sh create mode 100755 .github/scripts/generate-release-notes.sh create mode 100755 .github/scripts/read-version.sh delete mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/pr.yml delete mode 100644 .github/workflows/release-drafter.yml diff --git a/.github/actions/build-deb/action.yml b/.github/actions/build-deb/action.yml new file mode 100644 index 0000000..ca4f65e --- /dev/null +++ b/.github/actions/build-deb/action.yml @@ -0,0 +1,23 @@ +name: 'Build Debian Package' +description: 'Build HALPI2 daemon .deb package' + +runs: + using: 'composite' + steps: + - name: Create minimal .env file + run: | + if [ ! -f .env ]; then + echo "# Environment file for GitHub Actions" > .env + fi + shell: bash + + - name: Build package + run: ./run package:deb:docker:ci + shell: bash + + - name: Collect built packages + run: | + # Find .deb files created by dpkg-buildpackage (in parent directory) + find . .. -maxdepth 1 -name "*.deb" -exec mv {} ./ \; 2>/dev/null || true + ls -lh *.deb + shell: bash diff --git a/.github/actions/run-tests/action.yml b/.github/actions/run-tests/action.yml new file mode 100644 index 0000000..7318c76 --- /dev/null +++ b/.github/actions/run-tests/action.yml @@ -0,0 +1,17 @@ +name: 'Run Tests' +description: 'Run Python tests for HALPI2 daemon' + +runs: + using: 'composite' + steps: + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install uv + uses: astral-sh/setup-uv@v4 + + - name: Run tests + run: uv run pytest + shell: bash diff --git a/.github/scripts/check-release-exists.sh b/.github/scripts/check-release-exists.sh new file mode 100755 index 0000000..91a4111 --- /dev/null +++ b/.github/scripts/check-release-exists.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# Check if a release exists and set output flags +# Usage: check-release-exists.sh [RELEASE_TYPE] +# RELEASE_TYPE: "prerelease" (default), "draft", or "stable" + +set -e + +VERSION="${1:?Version required}" +RELEASE_TYPE="${2:-prerelease}" + +if [ -z "$VERSION" ]; then + echo "Error: VERSION argument required" + exit 1 +fi + +case "$RELEASE_TYPE" in + prerelease) + # Check if published (non-prerelease) release with same or higher version exists + HIGHEST_STABLE=$(gh release list --limit 100 --json tagName,isPrerelease,isDraft \ + --jq '.[] | select(.isDraft == false and .isPrerelease == false) | .tagName' | \ + sed 's/^v//' | sort -V | tail -n1) + + if [ -n "$HIGHEST_STABLE" ]; then + echo "Found highest stable release: v${HIGHEST_STABLE}" + # Compare versions using dpkg --compare-versions + # Strip Debian revision from VERSION for comparison (0.2.0-1 → 0.2.0) + # Note: ${VERSION%-*} is safe - if VERSION has no dash, it returns VERSION unchanged + if dpkg --compare-versions "${VERSION%-*}" le "$HIGHEST_STABLE"; then + echo "action=skip" >> "$GITHUB_OUTPUT" + echo "⏭️ Stable release v${HIGHEST_STABLE} >= v${VERSION%-*} - skipping pre-release" + exit 0 + fi + fi + echo "action=create" >> "$GITHUB_OUTPUT" + echo "✅ No published release with same or higher version - will create pre-release v${VERSION%-*}" + ;; + + draft) + # Check if release exists (any kind) + if gh release view "v$VERSION" &>/dev/null; then + IS_DRAFT=$(gh release view "v$VERSION" --json isDraft --jq '.isDraft') + if [ "$IS_DRAFT" = "true" ]; then + echo "skip=false" >> "$GITHUB_OUTPUT" + echo "delete_existing=true" >> "$GITHUB_OUTPUT" + echo "Existing draft release found - will delete and recreate" + else + echo "skip=true" >> "$GITHUB_OUTPUT" + echo "delete_existing=false" >> "$GITHUB_OUTPUT" + echo "Published release v$VERSION already exists - skipping" + fi + else + echo "skip=false" >> "$GITHUB_OUTPUT" + echo "delete_existing=false" >> "$GITHUB_OUTPUT" + echo "No existing release found" + fi + ;; + + stable) + # For stable releases, check if prerelease exists to delete first + if gh release view "v$VERSION" &>/dev/null; then + IS_PRERELEASE=$(gh release view "v$VERSION" --json isPrerelease --jq '.isPrerelease') + if [ "$IS_PRERELEASE" = "true" ]; then + echo "action=delete" >> "$GITHUB_OUTPUT" + echo "🗑️ Existing pre-release v$VERSION found - will delete before creating stable" + else + echo "action=skip" >> "$GITHUB_OUTPUT" + echo "⏭️ Published release v$VERSION already exists - skipping" + fi + else + echo "action=create" >> "$GITHUB_OUTPUT" + echo "✅ No existing release found - will create v$VERSION" + fi + ;; + + *) + echo "Error: Unknown RELEASE_TYPE '$RELEASE_TYPE'. Use 'prerelease', 'draft', or 'stable'" + exit 1 + ;; +esac diff --git a/.github/scripts/generate-release-notes.sh b/.github/scripts/generate-release-notes.sh new file mode 100755 index 0000000..92371b4 --- /dev/null +++ b/.github/scripts/generate-release-notes.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# Generate release notes for a release +# Usage: generate-release-notes.sh +# RELEASE_TYPE: "prerelease", "draft", or "stable" + +set -e + +VERSION="${1:?Version required}" +TAG_VERSION="${2:?Tag version required}" +RELEASE_TYPE="${3:?Release type required}" + +if [ -z "$VERSION" ] || [ -z "$TAG_VERSION" ] || [ -z "$RELEASE_TYPE" ]; then + echo "Usage: generate-release-notes.sh " + exit 1 +fi + +SHORT_SHA="${GITHUB_SHA:0:7}" + +# Get the latest published (non-prerelease) release +LAST_TAG=$(gh release list --limit 100 --json tagName,isPrerelease,isDraft \ + --jq '.[] | select(.isDraft == false and .isPrerelease == false) | .tagName' | head -n1) + +if [ -n "$LAST_TAG" ]; then + echo "Generating changelog since $LAST_TAG" + CHANGELOG=$(git log "${LAST_TAG}"..HEAD --pretty=format:"- %s (%h)" --no-merges --) +else + echo "No previous published releases found, using recent commits" + CHANGELOG=$(git log -10 --pretty=format:"- %s (%h)" --no-merges) +fi + +case "$RELEASE_TYPE" in + prerelease) + cat > release_notes.md < release_notes.md < release_notes.md <> "$GITHUB_OUTPUT" +echo "tag_version=$TAG_VERSION" >> "$GITHUB_OUTPUT" +echo "Version from VERSION file: $VERSION (tag version: $TAG_VERSION)" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 91bd228..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: build - -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.11", "3.12", "3.13"] - - steps: - - uses: actions/checkout@v5 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install uv - run: ./run uv-download - - - name: Set up cache - uses: actions/cache@v4 - with: - path: .venv - key: venv-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}-${{ hashFiles('uv.lock') }} - - name: Install dependencies - run: | - ./run install - - - name: Run style checks - run: | - ./run lint diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..3fa7553 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,158 @@ +name: Main Branch CI/CD + +on: + push: + branches: [main] + +permissions: + contents: write + +env: + APT_DISTRO: ${{ vars.APT_DISTRO || 'trixie' }} + APT_COMPONENT: ${{ vars.APT_COMPONENT || 'hatlabs' }} + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run tests + uses: ./.github/actions/run-tests + + build-and-release: + needs: test + runs-on: ubuntu-latest-arm64 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Read version from VERSION + id: version + run: .github/scripts/read-version.sh + + - name: Check if published release exists + id: check + run: .github/scripts/check-release-exists.sh "${{ steps.version.outputs.version }}" prerelease + env: + GH_TOKEN: ${{ github.token }} + + - name: Build .deb package + if: steps.check.outputs.action == 'create' + uses: ./.github/actions/build-deb + + - name: Rename package with distro+component suffix + if: steps.check.outputs.action == 'create' + run: | + VERSION="${{ steps.version.outputs.version }}" + OLD_NAME="halpi2-daemon_${VERSION}_arm64.deb" + NEW_NAME="halpi2-daemon_${VERSION}_arm64+${APT_DISTRO}+${APT_COMPONENT}.deb" + + if [ -f "$OLD_NAME" ]; then + echo "📦 Renaming package: $(basename $OLD_NAME) → $(basename $NEW_NAME)" + mv "$OLD_NAME" "$NEW_NAME" + echo "✅ Package renamed successfully" + echo "Package location: $NEW_NAME" + else + echo "❌ Error: Expected package not found: $OLD_NAME" + exit 1 + fi + + - name: Generate release notes + if: steps.check.outputs.action == 'create' + id: notes + run: .github/scripts/generate-release-notes.sh "${{ steps.version.outputs.version }}" "${{ steps.version.outputs.tag_version }}" prerelease + env: + GH_TOKEN: ${{ github.token }} + + - name: Delete existing pre-release + if: steps.check.outputs.action == 'create' + run: | + TAG_VERSION="${{ steps.version.outputs.tag_version }}" + if gh release view "v${TAG_VERSION}" &>/dev/null; then + IS_PRERELEASE=$(gh release view "v${TAG_VERSION}" --json isPrerelease --jq '.isPrerelease') + if [ "$IS_PRERELEASE" = "true" ]; then + echo "🗑️ Deleting existing pre-release v${TAG_VERSION}" + gh release delete "v${TAG_VERSION}" --yes --cleanup-tag + fi + fi + env: + GH_TOKEN: ${{ github.token }} + + - name: Create pre-release + if: steps.check.outputs.action == 'create' + run: | + TAG_VERSION="${{ steps.version.outputs.tag_version }}" + if ! ls *.deb 1> /dev/null 2>&1; then + echo "❌ Error: No .deb files found" + exit 1 + fi + echo "📦 Creating pre-release v${TAG_VERSION}" + gh release create "v${TAG_VERSION}" \ + --prerelease \ + --title "v${TAG_VERSION} (Pre-release)" \ + --notes-file release_notes.md \ + *.deb + echo "✅ Pre-release created successfully" + env: + GH_TOKEN: ${{ github.token }} + + - name: Create draft release + if: steps.check.outputs.action == 'create' + run: | + VERSION="${{ steps.version.outputs.version }}" + TAG_VERSION="${{ steps.version.outputs.tag_version }}" + + # Check if draft release already exists + if gh release view "v${VERSION}" &>/dev/null; then + IS_DRAFT=$(gh release view "v${VERSION}" --json isDraft --jq '.isDraft') + IS_PRERELEASE=$(gh release view "v${VERSION}" --json isPrerelease --jq '.isPrerelease') + + if [ "$IS_DRAFT" = "true" ] && [ "$IS_PRERELEASE" = "false" ]; then + echo "Draft release v${VERSION} already exists, skipping creation" + fi + else + # Generate release notes for draft + .github/scripts/generate-release-notes.sh "${VERSION}" "${VERSION}" draft + + echo "📋 Creating draft release v${VERSION}" + gh release create "v${VERSION}" \ + --draft \ + --title "v${VERSION}" \ + --notes-file release_notes.md + echo "✅ Draft release created successfully" + fi + env: + GH_TOKEN: ${{ github.token }} + + - name: Dispatch to APT repository + if: steps.check.outputs.action == 'create' + uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ secrets.REPO_DISPATCH_PAT }} + repository: hatlabs/apt.hatlabs.fi + event-type: package-updated + client-payload: | + { + "repository": "${{ github.repository }}", + "distro": "${{ env.APT_DISTRO }}", + "channel": "unstable", + "component": "${{ env.APT_COMPONENT }}" + } + + - name: Report success + if: steps.check.outputs.action == 'create' + run: | + VERSION="${{ steps.version.outputs.version }}" + TAG_VERSION="${{ steps.version.outputs.tag_version }}" + echo "=== Main Branch CI/CD Complete ===" + echo "Package version: ${VERSION}" + echo "Release tag: v${TAG_VERSION}" + echo "Release URL: https://github.com/${{ github.repository }}/releases/tag/v${TAG_VERSION}" + echo "" + echo "✅ Pre-release created" + echo "✅ Draft release created" + echo "✅ Dispatched to apt.hatlabs.fi unstable channel" diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..4262322 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,19 @@ +name: Pull Request Checks + +on: + pull_request: + branches: [ main ] + +permissions: + contents: read + +jobs: + tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run tests + uses: ./.github/actions/run-tests diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml deleted file mode 100644 index 9760b1c..0000000 --- a/.github/workflows/release-drafter.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Release Drafter - -on: - push: - # branches to consider in the event; optional, defaults to all - branches: - - main - -jobs: - update_release_draft: - runs-on: ubuntu-latest - steps: - # Drafts your next Release notes as Pull Requests are merged into "master" - - uses: release-drafter/release-drafter@v6 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9b6791d..3a4c521 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,56 +1,32 @@ -name: Build and Release Package +name: Release Published on: - push: - tags: ['v*'] - -jobs: - build-and-release: - runs-on: ubuntu-latest-arm64 - container: debian:bookworm - - steps: - - uses: actions/checkout@v5 - - - name: Install build dependencies - run: | - apt-get update - apt-get install -y \ - debhelper \ - dh-virtualenv \ - dh-make \ - devscripts \ - build-essential \ - python3-dev \ - python3-venv \ - python3-pip \ - git \ - vim \ - && rm -rf /var/lib/apt/lists/* + release: + types: [published] +permissions: + contents: read - - name: Build package - run: | - dpkg-buildpackage -us -uc - mkdir -p dist - mv ../*.deb dist/ +env: + APT_DISTRO: ${{ vars.APT_DISTRO || 'trixie' }} + APT_COMPONENT: ${{ vars.APT_COMPONENT || 'hatlabs' }} - - name: Create Release - uses: softprops/action-gh-release@v2 - with: - files: dist/*.deb - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Trigger APT repository update +jobs: + trigger-packaging: + runs-on: ubuntu-latest + # Only handle stable releases - pre-releases are handled by auto-prerelease.yml + if: ${{ github.event.release.prerelease == false }} + steps: + - name: Trigger APT repository uses: peter-evans/repository-dispatch@v3 with: - token: ${{ secrets.APT_REPO_PAT }} + token: ${{ secrets.REPO_DISPATCH_PAT }} repository: hatlabs/apt.hatlabs.fi event-type: package-updated client-payload: | { - "package": "${{ github.event.repository.name }}", - "version": "${{ github.ref_name }}", - "repository": "${{ github.repository }}" + "repository": "${{ github.repository }}", + "distro": "${{ env.APT_DISTRO }}", + "channel": "stable", + "component": "${{ env.APT_COMPONENT }}" } From 16235dbe455e2f7d540c3d7420067756a6eed416 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Thu, 20 Nov 2025 11:49:21 +0200 Subject: [PATCH 2/6] fix(ci): address PR review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Simplify .bumpversion.cfg to match cockpit-apt pattern - Add VERSION file as canonical version source - Fix generate-release-notes.sh to reference HALPI2 daemon instead of Cockpit APT - Add bumpversion command to run script for version management Addresses all issues raised in PR #33 review: 1. Fixed all "Cockpit APT" references in release notes 2. Added VERSION file and updated bumpversion config 3. Architecture remains hardcoded to arm64 (acceptable for HALPI2) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .bumpversion.cfg | 11 ++--- .github/scripts/generate-release-notes.sh | 60 +++++++++++++---------- run | 35 +++++++++++++ 3 files changed, 74 insertions(+), 32 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 05bc9bd..525dced 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,13 +1,10 @@ [bumpversion] current_version = 4.0.5 -commit = True -parse = (?P\d+)(\.(?P\d+))(\.(?P\d+))(\-(?P.*))? -serialize = - {major}.{minor}.{patch}-{release} - {major}.{minor}.{patch} +commit = False +tag = False [bumpversion:file:VERSION] [bumpversion:file:pyproject.toml] - -[bumpversion:file:src/halpi/const.py] +search = version = "{current_version}" +replace = version = "{new_version}" diff --git a/.github/scripts/generate-release-notes.sh b/.github/scripts/generate-release-notes.sh index 92371b4..587e112 100755 --- a/.github/scripts/generate-release-notes.sh +++ b/.github/scripts/generate-release-notes.sh @@ -31,7 +31,7 @@ fi case "$RELEASE_TYPE" in prerelease) cat > release_notes.md < release_notes.md < release_notes.md < /dev/null; then + echo "Error: bumpversion not installed" + echo "Install with: pip install bump2version" + exit 1 + fi + + # Run bumpversion + bumpversion "$BUMP_TYPE" + + echo "✅ Version bumped successfully" + echo "📝 Remember to commit the version changes:" + echo " git add VERSION pyproject.toml .bumpversion.cfg" + echo " git commit -m \"chore: bump version to \$(cat VERSION)\"" +} + ################################################################################ # Package Management Commands From 694d75c08528c2155d2e2bce2f049dbf7b190eb6 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Thu, 20 Nov 2025 11:55:47 +0200 Subject: [PATCH 3/6] refactor: update run script to use hyphen-separated naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert all command names from colon-separated (e.g., package:deb) to hyphen-separated (e.g., package-deb) to match the naming scheme used in cockpit-apt and other HaLOS repositories. Changes: - release:version → release-version - package:deb → package-deb - package:deb:only → package-deb-only - package:deb:docker → package-deb-docker - package:docker:build → package-docker-build - ci:check → ci-check - ci:build → ci-build - dev:env → dev-env - dev:version:bump → dev-version-bump - dev:version:dry-run → dev-version-dry-run - dev:version:show → dev-version-show - docker:build → docker-build - docker:remove → docker-remove Backward compatibility: - Added colon-separated aliases for all renamed commands - Existing scripts and workflows will continue to work 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- run | 83 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/run b/run index 1652f1b..e90428d 100755 --- a/run +++ b/run @@ -68,7 +68,7 @@ function clean { build-remove } -function release:version { +function release-version { #@ Show current project version #@ Category: Core Development cat VERSION @@ -112,24 +112,24 @@ function bumpversion { ################################################################################ # Package Management Commands -function package:deb { +function package-deb { #@ Build Debian package (native) #@ Category: Package Management echo "🏗️ Building Debian package..." - package:deb:only + package-deb-only } -function package:deb:only { +function package-deb-only { #@ Build Debian package from existing artifacts (internal) #@ Category: Package Management echo "📦 Creating Debian package..." # Set up environment - dev:env + dev-env export DEBEMAIL="info@hatlabs.fi" export DEBFULLNAME="Hat Labs CI" - export PACKAGE_VERSION=$(release:version) + export PACKAGE_VERSION=$(release-version) DEB_VERSION=$(echo "$PACKAGE_VERSION" | sed 's/-\([a-zA-Z]\)/~\1/g') # Create a new changelog entry @@ -143,7 +143,7 @@ function package:deb:only { echo "✅ Debian package built successfully" } -function package:deb:docker { +function package-deb-docker { #@ Build Debian package using Docker container #@ Category: Package Management echo "🐳 Building Debian package using Docker..." @@ -151,12 +151,12 @@ function package:deb:docker { # Use Docker container for Debian packaging echo "🐳 Running Debian packaging in Docker container..." export DIR_NAME=$(basename "$PWD") - docker compose -f docker/docker-compose.debtools.yml run --rm debtools ./run package:deb:only + docker compose -f docker/docker-compose.debtools.yml run --rm debtools ./run package-deb-only echo "✅ Docker-based Debian package built successfully" } -function package:docker:build { +function package-docker-build { #@ Build Docker tools image #@ Category: Package Management export DIR_NAME=$(basename "$PWD") @@ -166,7 +166,7 @@ function package:docker:build { ################################################################################ # Testing/CI Commands -function ci:check { +function ci-check { #@ Run CI verification checks (lint + test) #@ Category: Testing/CI echo "🔍 Running CI verification checks..." @@ -175,13 +175,13 @@ function ci:check { echo "✅ CI checks passed" } -function ci:build { +function ci-build { #@ Full CI build pipeline (lint + test + package) #@ Category: Testing/CI echo "🚀 Running full CI build pipeline..." clean - ci:check - package:deb:docker + ci-check + package-deb-docker echo "✅ CI build pipeline completed successfully" } @@ -218,58 +218,58 @@ function pull { --exclude='.venv' halpi2:src/halpid/ . } -function dev:env { +function dev-env { #@ Show/check development environment #@ Category: Development Utilities _env } -function dev:version:bump { +function dev-version-bump { #@ Bump to specific version (e.g. 3.2.0) - #@ Usage: dev:version:bump + #@ Usage: dev-version-bump #@ Category: Development Utilities local new_version="${1:-}" if [ -z "$new_version" ]; then - echo "Error: Version required. Usage: dev:version:bump " - echo "Current version: $(release:version)" - echo "Example: ./run dev:version:bump 3.2.0" + echo "Error: Version required. Usage: dev-version-bump " + echo "Current version: $(release-version)" + echo "Example: ./run dev-version-bump 3.2.0" exit 1 fi - echo "🔖 Bumping version from $(release:version) to $new_version..." + echo "🔖 Bumping version from $(release-version) to $new_version..." bump2version --new-version "$new_version" patch - echo "✓ Version bumped to $(release:version)" + echo "✓ Version bumped to $(release-version)" } -function dev:version:dry-run { +function dev-version-dry-run { #@ Preview version change without applying - #@ Usage: dev:version:dry-run + #@ Usage: dev-version-dry-run #@ Category: Development Utilities local new_version="${1:-}" if [ -z "$new_version" ]; then - echo "Error: Version required. Usage: dev:version:dry-run " - echo "Current version: $(release:version)" - echo "Example: ./run dev:version:dry-run 3.2.0" + echo "Error: Version required. Usage: dev-version-dry-run " + echo "Current version: $(release-version)" + echo "Example: ./run dev-version-dry-run 3.2.0" exit 1 fi - echo "Current version: $(release:version)" + echo "Current version: $(release-version)" echo "Preview of changes for version $new_version:" bump2version --new-version "$new_version" patch --dry-run --verbose } -function dev:version:show { +function dev-version-show { #@ Show current version #@ Category: Development Utilities - release:version + release-version } ################################################################################ # Docker Commands -function docker:build { +function docker-build { #@ Build the Docker image #@ Category: Docker echo Building docker ${DOCKER_IMAGE}:${DOCKER_IMAGE_VERSION} ... @@ -277,7 +277,7 @@ function docker:build { -f ./docker/Dockerfile --no-cache } -function docker:remove { +function docker-remove { #@ Remove the Docker image #@ Category: Docker echo Removing docker ${DOCKER_IMAGE}:${DOCKER_IMAGE_VERSION} ... @@ -327,12 +327,27 @@ function debtools { } function build-debian { - package:deb:only + package-deb-only } function debtools-build { - package:deb:docker -} + package-deb-docker +} + +# Colon-separated aliases (deprecated, use hyphen-separated) +function release:version { release-version "$@"; } +function package:deb { package-deb "$@"; } +function package:deb:only { package-deb-only "$@"; } +function package:deb:docker { package-deb-docker "$@"; } +function package:docker:build { package-docker-build "$@"; } +function ci:check { ci-check "$@"; } +function ci:build { ci-build "$@"; } +function dev:env { dev-env "$@"; } +function dev:version:bump { dev-version-bump "$@"; } +function dev:version:dry-run { dev-version-dry-run "$@"; } +function dev:version:show { dev-version-show "$@"; } +function docker:build { docker-build "$@"; } +function docker:remove { docker-remove "$@"; } ################################################################################ # Project-specific commands end. From d70b09275e05aed309c63500d50a9ddb906bdf3d Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Thu, 20 Nov 2025 12:23:30 +0200 Subject: [PATCH 4/6] fix(ci): correct build command in build-deb action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update from non-existent package:deb:docker:ci to package-deb-docker. The :ci suffix was incorrect - the command should just be package-deb-docker which builds the Debian package using the Docker container. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/actions/build-deb/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/build-deb/action.yml b/.github/actions/build-deb/action.yml index ca4f65e..96b22d4 100644 --- a/.github/actions/build-deb/action.yml +++ b/.github/actions/build-deb/action.yml @@ -12,7 +12,7 @@ runs: shell: bash - name: Build package - run: ./run package:deb:docker:ci + run: ./run package-deb-docker shell: bash - name: Collect built packages From afd2038f4cf2d1d0080c69f4e0df23c3adb7fbe6 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Thu, 20 Nov 2025 12:40:57 +0200 Subject: [PATCH 5/6] refactor: simplify run script command names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Further simplify command naming to match cockpit-apt patterns: Command Name Changes: - release-version → version - package-deb → build-deb - package-deb-only → (merged into build-deb) - package-deb-docker → docker-build-deb - package-docker-build → build-docker-tools - dev-version-bump → (removed, use bumpversion directly) - dev-version-dry-run → bumpversion-dry-run - dev-version-show → (removed, use version directly) - docker-build → build-docker - docker-remove → remove-docker - uv-download → install-uv Simplifications: - Merged package-deb-only into build-deb (simpler structure) - Changed bumpversion to simple wrapper that forwards all args - Moved debtools from legacy section to Development Utilities - Removed all backward compatibility aliases (clean slate) - Updated .github/actions/build-deb/action.yml to use docker-build-deb Benefits: - Consistent verb-noun or action-object naming - Simpler command structure - Better alignment with cockpit-apt conventions - bumpversion now supports all bump2version arguments directly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/actions/build-deb/action.yml | 2 +- run | 125 +++++---------------------- 2 files changed, 24 insertions(+), 103 deletions(-) diff --git a/.github/actions/build-deb/action.yml b/.github/actions/build-deb/action.yml index 96b22d4..aab7e2f 100644 --- a/.github/actions/build-deb/action.yml +++ b/.github/actions/build-deb/action.yml @@ -12,7 +12,7 @@ runs: shell: bash - name: Build package - run: ./run package-deb-docker + run: ./run docker-build-deb shell: bash - name: Collect built packages diff --git a/run b/run index e90428d..d54e38d 100755 --- a/run +++ b/run @@ -68,61 +68,26 @@ function clean { build-remove } -function release-version { +function version { #@ Show current project version #@ Category: Core Development cat VERSION } function bumpversion { - #@ Bump version using bumpversion tool (patch|minor|major) + #@ Bump version using bumpversion tool + #@ Usage: bumpversion [patch|minor|major] or bumpversion --new-version X.Y.Z patch #@ Category: Core Development - local BUMP_TYPE="${1:-}" - - if [[ -z "$BUMP_TYPE" ]]; then - echo "Error: version bump type required" - echo "Usage: ./run bumpversion [patch|minor|major]" - exit 1 - fi - - if [[ ! "$BUMP_TYPE" =~ ^(patch|minor|major)$ ]]; then - echo "Error: invalid bump type '$BUMP_TYPE'" - echo "Usage: ./run bumpversion [patch|minor|major]" - exit 1 - fi - - echo "🔢 Bumping $BUMP_TYPE version..." - - # Check if bumpversion is installed - if ! command -v bumpversion &> /dev/null; then - echo "Error: bumpversion not installed" - echo "Install with: pip install bump2version" - exit 1 - fi - - # Run bumpversion - bumpversion "$BUMP_TYPE" - - echo "✅ Version bumped successfully" - echo "📝 Remember to commit the version changes:" - echo " git add VERSION pyproject.toml .bumpversion.cfg" - echo " git commit -m \"chore: bump version to \$(cat VERSION)\"" + command bumpversion "$@" } ################################################################################ # Package Management Commands -function package-deb { +function build-deb { #@ Build Debian package (native) #@ Category: Package Management echo "🏗️ Building Debian package..." - package-deb-only -} - -function package-deb-only { - #@ Build Debian package from existing artifacts (internal) - #@ Category: Package Management - echo "📦 Creating Debian package..." # Set up environment dev-env @@ -143,7 +108,7 @@ function package-deb-only { echo "✅ Debian package built successfully" } -function package-deb-docker { +function docker-build-deb { #@ Build Debian package using Docker container #@ Category: Package Management echo "🐳 Building Debian package using Docker..." @@ -151,12 +116,12 @@ function package-deb-docker { # Use Docker container for Debian packaging echo "🐳 Running Debian packaging in Docker container..." export DIR_NAME=$(basename "$PWD") - docker compose -f docker/docker-compose.debtools.yml run --rm debtools ./run package-deb-only + debtools ./run build-deb-only echo "✅ Docker-based Debian package built successfully" } -function package-docker-build { +function build-docker-tools { #@ Build Docker tools image #@ Category: Package Management export DIR_NAME=$(basename "$PWD") @@ -181,7 +146,7 @@ function ci-build { echo "🚀 Running full CI build pipeline..." clean ci-check - package-deb-docker + docker-build-deb echo "✅ CI build pipeline completed successfully" } @@ -224,52 +189,36 @@ function dev-env { _env } -function dev-version-bump { - #@ Bump to specific version (e.g. 3.2.0) - #@ Usage: dev-version-bump +function debtools { + #@ Run a command inside the debtools Docker container + #@ Usage: debtools [args] #@ Category: Development Utilities - local new_version="${1:-}" - - if [ -z "$new_version" ]; then - echo "Error: Version required. Usage: dev-version-bump " - echo "Current version: $(release-version)" - echo "Example: ./run dev-version-bump 3.2.0" - exit 1 - fi - - echo "🔖 Bumping version from $(release-version) to $new_version..." - bump2version --new-version "$new_version" patch - echo "✓ Version bumped to $(release-version)" + export DIR_NAME=$(basename "$PWD") + docker compose -f docker/docker-compose.debtools.yml run --rm debtools "$@" } -function dev-version-dry-run { +function bumpversion-dry-run { #@ Preview version change without applying - #@ Usage: dev-version-dry-run + #@ Usage: bumpversion-dry-run #@ Category: Development Utilities local new_version="${1:-}" if [ -z "$new_version" ]; then - echo "Error: Version required. Usage: dev-version-dry-run " - echo "Current version: $(release-version)" - echo "Example: ./run dev-version-dry-run 3.2.0" + echo "Error: Version required. Usage: bumpversion-dry-run " + echo "Current version: $(version)" + echo "Example: ./run bumpversion-dry-run 3.2.0" exit 1 fi - echo "Current version: $(release-version)" + echo "Current version: $(version)" echo "Preview of changes for version $new_version:" bump2version --new-version "$new_version" patch --dry-run --verbose } -function dev-version-show { - #@ Show current version - #@ Category: Development Utilities - release-version -} - ################################################################################ # Docker Commands -function docker-build { +function build-docker { #@ Build the Docker image #@ Category: Docker echo Building docker ${DOCKER_IMAGE}:${DOCKER_IMAGE_VERSION} ... @@ -277,7 +226,7 @@ function docker-build { -f ./docker/Dockerfile --no-cache } -function docker-remove { +function remove-docker { #@ Remove the Docker image #@ Category: Docker echo Removing docker ${DOCKER_IMAGE}:${DOCKER_IMAGE_VERSION} ... @@ -287,7 +236,7 @@ function docker-remove { ################################################################################ # Setup/Installation Commands -function uv-download { +function install-uv { #@ Download and install the latest version of uv #@ Category: Setup/Installation curl -LsSf https://astral.sh/uv/install.sh | sh @@ -320,34 +269,6 @@ function build-remove { rm -rf build/ 2>/dev/null || true } -# Legacy aliases for backward compatibility -function debtools { - export DIR_NAME=$(basename "$PWD") - docker compose -f docker/docker-compose.debtools.yml run --rm debtools "$@" -} - -function build-debian { - package-deb-only -} - -function debtools-build { - package-deb-docker -} - -# Colon-separated aliases (deprecated, use hyphen-separated) -function release:version { release-version "$@"; } -function package:deb { package-deb "$@"; } -function package:deb:only { package-deb-only "$@"; } -function package:deb:docker { package-deb-docker "$@"; } -function package:docker:build { package-docker-build "$@"; } -function ci:check { ci-check "$@"; } -function ci:build { ci-build "$@"; } -function dev:env { dev-env "$@"; } -function dev:version:bump { dev-version-bump "$@"; } -function dev:version:dry-run { dev-version-dry-run "$@"; } -function dev:version:show { dev-version-show "$@"; } -function docker:build { docker-build "$@"; } -function docker:remove { docker-remove "$@"; } ################################################################################ # Project-specific commands end. From 40f205d7211b2881978d5301a4921fa3810b24ae Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Thu, 20 Nov 2025 13:34:42 +0200 Subject: [PATCH 6/6] config: enable automatic commits in bumpversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set commit = True in .bumpversion.cfg to automatically create commits when bumping versions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .bumpversion.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 589074d..dd9a5f6 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,6 +1,6 @@ [bumpversion] current_version = 4.0.7 -commit = False +commit = True tag = False [bumpversion:file:VERSION]