Skip to content

Commit c1fe3de

Browse files
committed
feat: enhance post-commit hook for automatic version bump and user notifications release:patch
1 parent ce1a811 commit c1fe3de

8 files changed

Lines changed: 57 additions & 64 deletions

File tree

.githooks/post-commit

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
#!/bin/sh
22
#
33
# PairUX Post-Commit Hook
4-
# Notifies user if a release will be triggered on push.
4+
# Runs version bump when a release trigger is detected in the commit message.
5+
#
6+
# Flow:
7+
# 1. User commits with "release:patch" in message
8+
# 2. pre-commit runs tests → passes
9+
# 3. commit-msg saves trigger to temp file
10+
# 4. post-commit (this hook) runs version:bump → creates version commit + tag
11+
# 5. User pushes → both commits and tag are included in the push
512
#
613

714
# Colors for output
15+
GREEN='\033[0;32m'
816
YELLOW='\033[1;33m'
17+
BLUE='\033[0;34m'
18+
RED='\033[0;31m'
919
NC='\033[0m' # No Color
1020

1121
# Temp file from commit-msg hook
@@ -14,8 +24,29 @@ RELEASE_TRIGGER_FILE="/tmp/.pairux-release-trigger"
1424
# Check if a release was triggered
1525
if [ -f "$RELEASE_TRIGGER_FILE" ]; then
1626
RELEASE_TYPE=$(cat "$RELEASE_TRIGGER_FILE")
27+
28+
# Remove trigger file BEFORE running version bump to prevent re-triggering
29+
rm -f "$RELEASE_TRIGGER_FILE"
30+
1731
echo ""
32+
echo "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
1833
echo "${YELLOW}📦 Release trigger detected: ${RELEASE_TYPE}${NC}"
19-
echo "${YELLOW} The release will run automatically after you push.${NC}"
34+
echo "${YELLOW} Running version bump...${NC}"
35+
echo "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
2036
echo ""
37+
38+
# Get the repo directory
39+
REPO_DIR="$(git rev-parse --show-toplevel)"
40+
41+
# Run the version bump (creates commit + tag, does NOT push)
42+
if (cd "$REPO_DIR" && pnpm version:bump "$RELEASE_TYPE" --from-hook); then
43+
echo ""
44+
echo "${GREEN}✅ Version bump complete.${NC}"
45+
echo "${YELLOW} Push with: git push --follow-tags${NC}"
46+
echo ""
47+
else
48+
echo ""
49+
echo "${RED}❌ Version bump failed! Push your commit and bump manually.${NC}"
50+
echo ""
51+
fi
2152
fi

.githooks/pre-push

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,10 @@
11
#!/bin/sh
22
#
33
# PairUX Pre-Push Hook
4-
# Triggers the release process after push completes if a release trigger was detected.
54
#
6-
# Flow:
7-
# 1. User commits with "release:patch" in message
8-
# 2. pre-commit runs tests → passes
9-
# 3. commit-msg saves trigger to temp file
10-
# 4. post-commit notifies user
11-
# 5. User pushes
12-
# 6. pre-push spawns background process and exits 0 (allows push)
13-
# 7. Push completes
14-
# 8. Background process runs release
5+
# The version bump and tagging now happen in the post-commit hook.
6+
# This hook just ensures a clean push.
157
#
168

17-
# Colors for output
18-
GREEN='\033[0;32m'
19-
YELLOW='\033[1;33m'
20-
BLUE='\033[0;34m'
21-
NC='\033[0m' # No Color
22-
23-
# Temp file from commit-msg hook
24-
RELEASE_TRIGGER_FILE="/tmp/.pairux-release-trigger"
25-
26-
# Check if a release was triggered
27-
if [ -f "$RELEASE_TRIGGER_FILE" ]; then
28-
RELEASE_TYPE=$(cat "$RELEASE_TRIGGER_FILE")
29-
30-
echo ""
31-
echo "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
32-
echo "${YELLOW}🚀 Release will run after push: ${RELEASE_TYPE}${NC}"
33-
echo "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
34-
echo ""
35-
36-
# Get the directory where the repo is located
37-
REPO_DIR="$(git rev-parse --show-toplevel)"
38-
39-
# Spawn a background process that waits for push to complete then runs release
40-
(
41-
# Wait a moment for the push to complete
42-
sleep 3
43-
44-
# Change to repo directory
45-
cd "$REPO_DIR" || exit 1
46-
47-
# Check if trigger file still exists (wasn't cleaned up)
48-
if [ -f "$RELEASE_TRIGGER_FILE" ]; then
49-
RELEASE_TYPE=$(cat "$RELEASE_TRIGGER_FILE")
50-
rm -f "$RELEASE_TRIGGER_FILE"
51-
52-
echo ""
53-
echo "${GREEN}✅ Push completed. Running release...${NC}"
54-
echo ""
55-
56-
# Run the release
57-
pnpm release "$RELEASE_TYPE"
58-
fi
59-
) &
60-
fi
61-
629
# Always allow the push to proceed
6310
exit 0

apps/desktop/src/main/platform/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
44
vi.mock('electron', () => ({
55
app: {
66
getName: vi.fn().mockReturnValue('PairUX'),
7+
getVersion: vi.fn().mockReturnValue('0.0.0-test'),
78
getPath: vi.fn().mockReturnValue('/test/path'),
89
isPackaged: false,
910
showAboutPanel: vi.fn(),

apps/desktop/src/main/platform/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface PlatformInfo {
2424
isX11: boolean;
2525
arch: string;
2626
version: string;
27+
appVersion: string;
2728
isElevated: boolean;
2829
hasScreenCaptureSupport: boolean;
2930
hasInputInjectionSupport: boolean;
@@ -87,6 +88,7 @@ export function getPlatformInfo(): PlatformInfo {
8788
arch: process.arch,
8889
version:
8990
typeof process.getSystemVersion === 'function' ? process.getSystemVersion() : 'unknown',
91+
appVersion: app.getVersion(),
9092
isElevated: isElevated(),
9193
hasScreenCaptureSupport: checkScreenCaptureSupport(),
9294
hasInputInjectionSupport: checkInputInjectionSupport(),

apps/desktop/src/preload/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export interface IPCChannels {
5252
platform: NodeJS.Platform;
5353
arch: string;
5454
version: string;
55+
appVersion: string;
5556
displayServer: DisplayServer;
5657
isWayland: boolean;
5758
};

apps/desktop/src/renderer/routes/settings.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export function SettingsPage() {
4646
const [platformInfo, setPlatformInfo] = useState<{
4747
platform: string;
4848
version: string;
49+
appVersion: string;
4950
} | null>(null);
5051
const [isSaving, setIsSaving] = useState(false);
5152
const [saveSuccess, setSaveSuccess] = useState(false);
@@ -128,6 +129,7 @@ export function SettingsPage() {
128129
setPlatformInfo({
129130
platform: info.platform,
130131
version: info.version,
132+
appVersion: info.appVersion,
131133
});
132134
});
133135
void api.invoke('recording:getDirectory', undefined).then((result) => {
@@ -355,6 +357,12 @@ export function SettingsPage() {
355357
<span className="text-sm text-muted-foreground">Application</span>
356358
<span className="text-sm font-medium">PairUX</span>
357359
</div>
360+
<div className="flex items-center justify-between">
361+
<span className="text-sm text-muted-foreground">Version</span>
362+
<span className="text-sm font-medium">
363+
{platformInfo?.appVersion ?? 'Loading...'}
364+
</span>
365+
</div>
358366
<div className="flex items-center justify-between">
359367
<span className="text-sm text-muted-foreground">Platform</span>
360368
<span className="text-sm font-medium capitalize">

scripts/release.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ function main() {
141141
console.log('\n🔖 Creating git commit and tag...');
142142

143143
try {
144-
exec('git add -A');
145-
exec(`git commit -m "chore(release): v${newVersion}"`);
144+
exec(`git add ${packagesToUpdate.join(' ')}`);
145+
exec(`git commit --no-verify -m "chore(release): v${newVersion}"`);
146146
exec(`git tag -a v${newVersion} -m "Release v${newVersion}"`);
147147

148148
console.log('\n🚀 Pushing to remote...');

scripts/version-bump.mjs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ function checkGitStatus() {
102102

103103
function main() {
104104
const args = process.argv.slice(2);
105-
const bumpType = args[0];
105+
const fromHook = args.includes('--from-hook');
106+
const bumpType = args.find((a) => !a.startsWith('--'));
106107

107108
if (!bumpType || !['major', 'minor', 'patch'].includes(bumpType)) {
108109
console.error('Usage: pnpm version:bump <major|minor|patch>');
@@ -113,8 +114,10 @@ function main() {
113114
process.exit(1);
114115
}
115116

116-
console.log('\n🔍 Checking git status...');
117-
checkGitStatus();
117+
if (!fromHook) {
118+
console.log('\n🔍 Checking git status...');
119+
checkGitStatus();
120+
}
118121

119122
// Read current version from root package.json
120123
const rootPkgPath = join(rootDir, 'package.json');
@@ -143,8 +146,8 @@ function main() {
143146
console.log('\n🔖 Creating git commit and tag...');
144147

145148
try {
146-
exec('git add -A');
147-
exec(`git commit -m "chore(release): v${newVersion}"`);
149+
exec(`git add ${packagesToUpdate.join(' ')}`);
150+
exec(`git commit --no-verify -m "chore(release): v${newVersion}"`);
148151
exec(`git tag -a v${newVersion} -m "Release v${newVersion}"`);
149152

150153
console.log(`\n✅ Version bumped to v${newVersion}`);

0 commit comments

Comments
 (0)