Skip to content
This repository was archived by the owner on Feb 15, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/scripts/calculate-revision.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash
# Calculate the next revision number for a given upstream version
# Finds all git tags matching v<upstream-version>+<N> or v<upstream-version>+<N>_pre
# Returns the next N value (highest N + 1), or 1 if no matching tags exist
#
# Usage: calculate-revision.sh <upstream-version>

set -euo pipefail

UPSTREAM_VERSION="${1:-}"

if [ -z "$UPSTREAM_VERSION" ]; then
echo "Error: Upstream version is required" >&2
echo "Usage: $0 <upstream-version>" >&2
exit 1
fi

# Remove 'v' prefix if present
UPSTREAM_VERSION="${UPSTREAM_VERSION#v}"

# Find all tags matching the pattern: v{version}+{N} or v{version}+{N}_pre
PATTERN="v${UPSTREAM_VERSION}+*"
MATCHING_TAGS=$(git tag -l "$PATTERN" 2>/dev/null || true)

if [ -z "$MATCHING_TAGS" ]; then
# No matching tags, this is the first build
echo "1"
exit 0
fi

# Extract revision numbers from tags and find max
MAX_REVISION=0
while IFS= read -r tag; do
# Extract the number between '+' and either end of string or '_'
if [[ $tag =~ \+([0-9]+)(_.*)?$ ]]; then
REVISION="${BASH_REMATCH[1]}"
if [ "$REVISION" -gt "$MAX_REVISION" ]; then
MAX_REVISION="$REVISION"
fi
fi
done <<< "$MATCHING_TAGS"

# Return next revision number
NEXT_REVISION=$((MAX_REVISION + 1))
echo "$NEXT_REVISION"
81 changes: 81 additions & 0 deletions .github/scripts/generate-changelog.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/bin/bash
set -euo pipefail

# Generate debian/changelog dynamically for CI builds
# Usage: generate-changelog.sh --upstream <version> --revision <N>

UPSTREAM=""
REVISION=""

while [[ $# -gt 0 ]]; do
case $1 in
--upstream)
UPSTREAM="$2"
shift 2
;;
--revision)
REVISION="$2"
shift 2
;;
*)
echo "Error: Unknown option $1" >&2
echo "Usage: $0 --upstream <version> --revision <N>" >&2
exit 1
;;
esac
done

if [ -z "$UPSTREAM" ] || [ -z "$REVISION" ]; then
echo "Error: Both --upstream and --revision are required" >&2
echo "Usage: $0 --upstream <version> --revision <N>" >&2
exit 1
fi

# Package name
PACKAGE_NAME="halpi2-daemon"

# Debian version format: upstream-revision
DEBIAN_VERSION="${UPSTREAM}-${REVISION}"

# Distribution (unstable for CI builds)
DISTRIBUTION="unstable"

# Urgency
URGENCY="medium"

# Maintainer information
MAINTAINER_NAME="${MAINTAINER_NAME:-Hat Labs}"
MAINTAINER_EMAIL="${MAINTAINER_EMAIL:-info@hatlabs.fi}"

# Date in RFC 2822 format
DATE=$(date -R)

# Get recent changes from git log
# Get commits since last published release tag
LAST_TAG=$(git tag -l "v*" --sort=-version:refname | grep -v "_pre" | head -n1 || echo "")

if [ -n "$LAST_TAG" ]; then
CHANGES=$(git log "${LAST_TAG}"..HEAD --pretty=format:" * %s" --no-merges || echo " * Build ${REVISION}")
else
# No previous tags, use recent commits
CHANGES=$(git log -10 --pretty=format:" * %s" --no-merges || echo " * Build ${REVISION}")
fi

# If no changes (shouldn't happen), use a default message
if [ -z "$CHANGES" ]; then
CHANGES=" * Build ${REVISION}"
fi

# Generate debian/changelog entry
cat > debian/changelog <<EOF
${PACKAGE_NAME} (${DEBIAN_VERSION}) ${DISTRIBUTION}; urgency=${URGENCY}

${CHANGES}

-- ${MAINTAINER_NAME} <${MAINTAINER_EMAIL}> ${DATE}
EOF

echo "Generated debian/changelog:"
echo " Version: ${DEBIAN_VERSION}"
echo " Distribution: ${DISTRIBUTION}"
cat debian/changelog
56 changes: 56 additions & 0 deletions .github/scripts/rename-packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash
set -euo pipefail

# Rename packages with distro+component suffix
# Usage: rename-packages.sh --version <debian-version> --distro <distro> --component <component>
#
# This script handles the ARM64 architecture package naming for HALPI2 daemon

VERSION=""
DISTRO=""
COMPONENT=""

while [[ $# -gt 0 ]]; do
case $1 in
--version)
VERSION="$2"
shift 2
;;
--distro)
DISTRO="$2"
shift 2
;;
--component)
COMPONENT="$2"
shift 2
;;
*)
echo "Error: Unknown option $1" >&2
echo "Usage: $0 --version <debian-version> --distro <distro> --component <component>" >&2
exit 1
;;
esac
done

if [ -z "$VERSION" ] || [ -z "$DISTRO" ] || [ -z "$COMPONENT" ]; then
echo "Error: All options are required" >&2
exit 1
fi

# Package name and architecture
PACKAGE_NAME="halpi2-daemon"
ARCH="arm64"

OLD_NAME="${PACKAGE_NAME}_${VERSION}_${ARCH}.deb"
NEW_NAME="${PACKAGE_NAME}_${VERSION}_${ARCH}+${DISTRO}+${COMPONENT}.deb"

if [ -f "$OLD_NAME" ]; then
echo "Renaming package: $OLD_NAME -> $NEW_NAME"
mv "$OLD_NAME" "$NEW_NAME"
echo "Package renamed successfully"
else
echo "Error: Expected package not found: $OLD_NAME" >&2
echo "Available .deb files:" >&2
ls -la *.deb 2>/dev/null || echo "None found" >&2
exit 1
fi
161 changes: 9 additions & 152 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,156 +4,13 @@ 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@v6

- 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@v6
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} with .deb package"
gh release create "v${VERSION}" \
--draft \
--title "v${VERSION}" \
--notes-file release_notes.md \
*.deb
echo "✅ Draft release created successfully with .deb attached"
fi
env:
GH_TOKEN: ${{ github.token }}

- name: Dispatch to APT repository
if: steps.check.outputs.action == 'create'
uses: peter-evans/repository-dispatch@v4
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 with .deb package"
echo "✅ Draft release created with .deb attached"
echo "✅ Dispatched to apt.hatlabs.fi unstable channel"
build-release:
uses: hatlabs/shared-workflows/.github/workflows/build-release.yml@main
with:
package-name: halpi2-daemon
package-description: 'HALPI2 hardware daemon (Python implementation)'
apt-component: hatlabs
runs-on: ubuntu-latest-arm64
secrets:
APT_REPO_PAT: ${{ secrets.APT_REPO_PAT }}
16 changes: 3 additions & 13 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,8 @@ name: Pull Request Checks

on:
pull_request:
branches: [ main ]

permissions:
contents: read
branches: [main]

jobs:
tests:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Run tests
uses: ./.github/actions/run-tests
checks:
uses: hatlabs/shared-workflows/.github/workflows/pr-checks.yml@main
Loading