Skip to content

Commit 6d5c0d8

Browse files
committed
feat: individual builds
1 parent ab62b0d commit 6d5c0d8

1 file changed

Lines changed: 247 additions & 29 deletions

File tree

.github/workflows/build.yml

Lines changed: 247 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,266 @@
1-
name: Build and Push Docker Image
1+
name: Build .deb Package for Raspberry Pi
22

33
on:
44
push:
5-
branches:
6-
- master
5+
branches: [master]
76

8-
concurrency:
9-
group: build-client
10-
cancel-in-progress: false
7+
permissions:
8+
contents: write
9+
10+
env:
11+
PKG_NAME: intercom-client
12+
PKG_ARCH: arm64
13+
PKG_DEPENDS: "libgstreamer1.0-0, gstreamer1.0-plugins-base, gstreamer1.0-plugins-good, libv4l-0"
1114

1215
jobs:
13-
build-and-push:
16+
bump:
17+
name: Bump version
1418
runs-on: ubuntu-22.04-arm
15-
19+
outputs:
20+
new_version: ${{ steps.semver.outputs.new_version }}
1621
steps:
17-
- name: Checkout repository
18-
uses: actions/checkout@v4
19-
20-
- name: Log in to private Docker registry
21-
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login docker.kmanning.ie:5000 -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
22+
- uses: actions/checkout@v5
23+
with:
24+
fetch-depth: 0
25+
token: ${{ secrets.GITHUB_TOKEN }}
2226

23-
- name: Build and push
27+
- name: Determine next version from conventional commits
28+
id: semver
2429
run: |
25-
IMAGE=docker.kmanning.ie:5000/intercom-client
30+
set -euo pipefail
2631
27-
# Collect tags
28-
TAGS="-t $IMAGE:latest -t $IMAGE:${{ github.sha }}"
29-
30-
# Add semver tag from pyproject.toml
31-
VERSION=$(python3 -c "
32+
CURRENT_VERSION=$(python3 -c "
3233
import re
3334
with open('pyproject.toml') as f:
3435
m = re.search(r'^version\s*=\s*\"([^\"]+)\"', f.read(), re.MULTILINE)
3536
print(m.group(1))
3637
")
37-
TAGS="$TAGS -t $IMAGE:v$VERSION"
38+
echo "Current version: ${CURRENT_VERSION}"
39+
40+
IFS='.' read -r MAJOR MINOR PATCH <<< "${CURRENT_VERSION}"
41+
42+
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
43+
44+
if [ -z "${LAST_TAG}" ]; then
45+
echo "No existing tags — analyzing all commits"
46+
COMMITS=$(git log --format='%s')
47+
else
48+
echo "Last tag: ${LAST_TAG}"
49+
COMMITS=$(git log "${LAST_TAG}"..HEAD --format='%s')
50+
fi
51+
52+
BUMP="patch"
53+
while IFS= read -r subject; do
54+
# Major: breaking change via ! suffix
55+
if echo "$subject" | grep -qE '^[a-zA-Z]+(\([^)]+\))?!:'; then
56+
BUMP="major"
57+
break
58+
fi
59+
# Major: BREAKING CHANGE in commit body
60+
HASH=$(git log --format='%H %s' | grep -F "${subject}" | head -1 | awk '{print $1}')
61+
if [ -n "${HASH}" ] && git log -1 --format='%B' "${HASH}" | grep -q 'BREAKING CHANGE'; then
62+
BUMP="major"
63+
break
64+
fi
65+
# Minor: feat commits
66+
if [ "${BUMP}" != "major" ] && echo "$subject" | grep -qE '^feat(\([^)]+\))?:'; then
67+
BUMP="minor"
68+
fi
69+
done <<< "${COMMITS}"
70+
71+
echo "Bump type: ${BUMP}"
72+
73+
case "${BUMP}" in
74+
major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
75+
minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
76+
patch) PATCH=$((PATCH + 1)) ;;
77+
esac
78+
79+
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
80+
echo "New version: ${NEW_VERSION}"
81+
echo "new_version=${NEW_VERSION}" >> "$GITHUB_OUTPUT"
82+
83+
- name: Update pyproject.toml version
84+
run: |
85+
NEW_VERSION="${{ steps.semver.outputs.new_version }}"
86+
sed -i 's/^version = ".*"/version = "'"${NEW_VERSION}"'"/' pyproject.toml
87+
echo "Updated pyproject.toml to ${NEW_VERSION}"
88+
grep "^version" pyproject.toml
89+
90+
- name: Configure git
91+
run: |
92+
git config user.name "github-actions[bot]"
93+
git config user.email "github-actions[bot]@users.noreply.github.com"
94+
95+
- name: Commit version bump and push tag
96+
run: |
97+
NEW_VERSION="${{ steps.semver.outputs.new_version }}"
98+
git add pyproject.toml
99+
git commit -m "chore: bump version to ${NEW_VERSION}"
100+
git tag "v${NEW_VERSION}"
101+
git push origin HEAD
102+
git push origin "v${NEW_VERSION}"
103+
104+
- name: Create GitHub Release
105+
uses: softprops/action-gh-release@v2
106+
with:
107+
tag_name: v${{ steps.semver.outputs.new_version }}
108+
generate_release_notes: true
109+
env:
110+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
111+
112+
test:
113+
name: Run tests
114+
needs: bump
115+
runs-on: ubuntu-22.04-arm
116+
steps:
117+
- uses: actions/checkout@v5
118+
with:
119+
ref: v${{ needs.bump.outputs.new_version }}
120+
121+
- name: Install uv
122+
uses: astral-sh/setup-uv@v7
123+
with:
124+
enable-cache: true
125+
cache-dependency-glob: uv.lock
126+
127+
- name: Install dependencies
128+
run: uv sync
129+
130+
- name: Run tests
131+
run: uv run pytest
132+
133+
build:
134+
name: Build .deb
135+
needs: [test, bump]
136+
runs-on: ubuntu-22.04-arm
137+
steps:
138+
- uses: actions/checkout@v5
139+
with:
140+
ref: v${{ needs.bump.outputs.new_version }}
141+
142+
- name: Install uv
143+
uses: astral-sh/setup-uv@v7
144+
with:
145+
enable-cache: true
146+
cache-dependency-glob: uv.lock
147+
148+
- name: Install project dependencies
149+
run: uv sync
150+
151+
- name: Install Nuitka
152+
run: uv pip install nuitka
153+
154+
- name: Cache Nuitka build output
155+
uses: actions/cache@v4
156+
with:
157+
path: |
158+
dist/
159+
build/
160+
main.build/
161+
main.dist/
162+
main.onefile-build/
163+
key: nuitka-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('uv.lock', 'main.py', 'intercomclient/**/*.py') }}
164+
165+
- name: Build native binary with Nuitka
166+
run: >
167+
uv run python -m nuitka
168+
--standalone
169+
--onefile
170+
--output-filename=intercom-client
171+
--output-dir=dist
172+
--include-package=intercomclient
173+
--include-package=aiortc
174+
--include-package=av
175+
--include-package=cv2
176+
--include-package=numpy
177+
--include-package=websockets
178+
--include-package=requests
179+
--include-package=jsonschema
180+
--include-package=boto3
181+
--include-package=botocore
182+
--include-package=cryptography
183+
--include-package=cffi
184+
--include-package=jmespath
185+
--include-package=transparenc_sdk
186+
--include-package-data=opencv_python.libs
187+
--include-package-data=cv2
188+
main.py
189+
190+
- name: Build .deb package
191+
run: |
192+
set -euo pipefail
193+
194+
PKG_VERSION="${{ needs.bump.outputs.new_version }}"
195+
PKG_DIR="dist/${PKG_NAME}_${PKG_VERSION}_${PKG_ARCH}"
196+
DEB_FILE="${PKG_DIR}.deb"
197+
198+
mkdir -p "${PKG_DIR}/usr/local/bin"
199+
mkdir -p "${PKG_DIR}/lib/systemd/system"
200+
mkdir -p "${PKG_DIR}/etc/intercom-client"
201+
mkdir -p "${PKG_DIR}/DEBIAN"
202+
203+
cp dist/intercom-client "${PKG_DIR}/usr/local/bin/"
204+
chmod 755 "${PKG_DIR}/usr/local/bin/intercom-client"
205+
206+
cat > "${PKG_DIR}/DEBIAN/control" <<EOF
207+
Package: ${PKG_NAME}
208+
Version: ${PKG_VERSION}
209+
Section: net
210+
Priority: optional
211+
Architecture: ${PKG_ARCH}
212+
Depends: ${PKG_DEPENDS}
213+
Maintainer: Intercom Team
214+
Description: Intercom Pi client for WebRTC live streaming
215+
Raspberry Pi client that connects to the intercom signaling server
216+
and streams live video via WebRTC.
217+
EOF
218+
219+
cat > "${PKG_DIR}/etc/intercom-client/env" <<EOF
220+
# Intercom Client Configuration
221+
# Set your environment variables here — these are sourced by the systemd service.
222+
#
223+
# OAUTH_CLIENT_ID=your_client_id
224+
# OAUTH_CLIENT_SECRET=your_client_secret
225+
# VIDEO_SOURCE=0
226+
# TOKEN_FILE_PATH=/home/pi/.config/intercom-client/tokens.json
227+
# WEBSOCKET_API_BASE_URL=wss://your-server.com/ws/live_stream
228+
# HTTP_API_BASE_URL=https://your-server.com
229+
EOF
230+
231+
cat > "${PKG_DIR}/lib/systemd/system/intercom-client.service" <<EOF
232+
[Unit]
233+
Description=Intercom Pi Client
234+
After=network-online.target
235+
Wants=network-online.target
236+
237+
[Service]
238+
Type=simple
239+
User=pi
240+
Group=pi
241+
EnvironmentFile=-/etc/intercom-client/env
242+
ExecStart=/usr/local/bin/intercom-client
243+
Restart=on-failure
244+
RestartSec=10
245+
246+
[Install]
247+
WantedBy=multi-user.target
248+
EOF
38249
39-
docker build \
40-
-f Dockerfile \
41-
$TAGS \
42-
.
250+
dpkg-deb --build "${PKG_DIR}"
43251
44-
docker push "$IMAGE:latest"
45-
docker push "$IMAGE:${{ github.sha }}"
46-
docker push "$IMAGE:v$VERSION"
252+
echo "--- Built package ---"
253+
ls -lh "${DEB_FILE}"
254+
echo ""
255+
echo "--- Package contents ---"
256+
dpkg-deb --contents "${DEB_FILE}"
257+
echo ""
258+
echo "--- Package info ---"
259+
dpkg-deb --info "${DEB_FILE}"
47260
48-
echo "Pushed: $IMAGE:latest, $IMAGE:${{ github.sha }}, $IMAGE:v$VERSION"
261+
- name: Upload .deb artifact
262+
uses: actions/upload-artifact@v4
263+
with:
264+
name: intercom-client-deb
265+
path: dist/intercom-client_*.deb
266+
retention-days: 30

0 commit comments

Comments
 (0)