Skip to content

Commit 44e27a7

Browse files
authored
Merge pull request #1 from SillyLittleTech/copilot/update-app-icon-and-cicd-workflows
Add CI/CD workflows, cross-platform porting docs, and new app icon
2 parents dc8378a + 1f91b94 commit 44e27a7

33 files changed

Lines changed: 5846 additions & 100 deletions

.github/copilot-instructions.md

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
# PinStick — Development & Porting Guide
2+
3+
## Project Overview
4+
5+
PinStick is a lightweight macOS note-pinning app (formerly named "Jot") built with Swift/SwiftUI. It lives in the `SillyLittleTech/PinStick` repository.
6+
7+
---
8+
9+
## Branch Strategy
10+
11+
| Branch | Purpose |
12+
|---|---|
13+
| `main` | Stable macOS app with ARM (Apple Silicon) support |
14+
| `cross-platform-dev` | Windows and Linux porting work |
15+
16+
### Working Rules
17+
- All production-ready macOS changes merge into `main`.
18+
- Cross-platform experiments stay on `cross-platform-dev` until proven stable and tested.
19+
- Bug fixes that apply to both platforms should be cherry-picked from `main` into `cross-platform-dev` (or vice-versa) rather than duplicated.
20+
- Open a PR to `main` only when the cross-platform work is validated through CI.
21+
22+
---
23+
24+
## ARM Support (Apple Silicon)
25+
26+
The app was originally built with x64 in mind. To make it ARM-native:
27+
28+
### Xcode Build Settings
29+
1. Open `Jot.xcodeproj` (unzip `Jot.xcodeproj.zip` first).
30+
2. Select the **Jot** target → **Build Settings**.
31+
3. Set **Architectures** to `$(ARCHS_STANDARD)` (includes `arm64` + `x86_64` automatically).
32+
4. Set **Build Active Architecture Only** to `No` for Release builds.
33+
5. Under **Deployment**, set **macOS Deployment Target** to `14.0` or later (matching the current project) for full Apple Silicon support.
34+
35+
### Verifying ARM Compatibility
36+
```bash
37+
# After building, check the binary supports both architectures
38+
lipo -info build/Release/PinStick.app/Contents/MacOS/PinStick
39+
# Expected: Architectures in the fat file: arm64 x86_64
40+
```
41+
42+
### Testing Recommendations
43+
- Build and run on Apple Silicon hardware (M1/M2/M3).
44+
- Use GitHub Actions `macos-latest` runners — they run on Apple Silicon and will catch ARM-specific issues in CI.
45+
- Run existing unit tests (`JotTests`) after the architecture change to confirm no regressions.
46+
47+
---
48+
49+
## Windows & Linux Porting Strategy
50+
51+
### Why Not a Full Rewrite Immediately?
52+
AI-generated cross-platform code can have platform-specific bugs that are impossible to catch without running the app. The strategy below uses CI runners and beta testers as the safety net, avoiding the need for local VMs.
53+
54+
### Framework Options
55+
56+
| Framework | Language | Pros | Cons |
57+
|---|---|---|---|
58+
| **Qt** | C++ | Native look, powerful, cross-platform | Steep learning curve, C++ |
59+
| **Tauri** | Rust + Web (HTML/CSS/JS) | Lightweight, modern, secure | Rust learning curve |
60+
| **Flutter** | Dart | Fast UI, growing desktop support | Non-native look by default |
61+
| **.NET MAUI** | C# | Microsoft-backed, good Windows support | Less mature on Linux |
62+
| **Electron** | JS/TypeScript | Easy, huge ecosystem | Large binary size |
63+
64+
**Recommendation for PinStick**: Given the app's simplicity (note editor + pin-to-front), **Tauri** is the best fit — it produces small binaries, uses web tech for the UI, and has first-class GitHub Actions support.
65+
66+
### Code Organization for Shared Logic
67+
68+
```
69+
PinStick/
70+
├── shared/ # Business logic shared across platforms
71+
│ ├── models/ # Note data model
72+
│ └── storage/ # Persistence layer
73+
├── macos/ # Native Swift/SwiftUI macOS app
74+
│ └── Sources/
75+
├── cross-platform/ # Tauri / Qt / Flutter app (cross-platform-dev branch)
76+
│ ├── src-tauri/ # Rust backend
77+
│ └── src/ # Web frontend (HTML/CSS/JS)
78+
└── .github/
79+
└── workflows/
80+
```
81+
82+
---
83+
84+
## GitHub Actions CI/CD
85+
86+
### Current Workflows
87+
88+
| Workflow | Trigger | What It Does |
89+
|---|---|---|
90+
| `prerelease.yml` | PR marked ready for review | Builds macOS app, creates prerelease; includes Windows/Linux placeholder job for future ports |
91+
| `build-and-release.yml` | Push to `main` | Builds macOS app, tags release, publishes; includes Windows/Linux placeholder job for future ports |
92+
93+
### Testing on Windows & Linux Without Local VMs
94+
95+
GitHub Actions provides free hosted runners for all major platforms:
96+
97+
```yaml
98+
strategy:
99+
matrix:
100+
os: [macos-latest, windows-latest, ubuntu-latest]
101+
runs-on: ${{ matrix.os }}
102+
```
103+
104+
This lets CI compile and test the cross-platform build on actual Windows and Linux machines without installing anything locally.
105+
106+
#### Docker for Lightweight Linux Testing
107+
```yaml
108+
- name: Test on Linux (Docker)
109+
uses: addnab/docker-run-action@v3
110+
with:
111+
image: ubuntu:22.04
112+
run: |
113+
./cross-platform/scripts/build-linux.sh
114+
./cross-platform/scripts/test-linux.sh
115+
```
116+
117+
#### Adding Cross-Platform Builds to Workflows (Future)
118+
When the cross-platform branch matures, extend `build-and-release.yml` with:
119+
```yaml
120+
- name: Build Windows App
121+
if: runner.os == 'Windows'
122+
run: |
123+
cd cross-platform
124+
npm run tauri build -- --target x86_64-pc-windows-msvc
125+
126+
- name: Build Linux App
127+
if: runner.os == 'Linux'
128+
run: |
129+
cd cross-platform
130+
npm run tauri build -- --target x86_64-unknown-linux-gnu
131+
```
132+
133+
---
134+
135+
## Beta Testing Program
136+
137+
For real-world validation without a local VM:
138+
139+
1. **macOS** — TestFlight or direct `.app.zip` distribution via GitHub Releases.
140+
2. **Windows** — GitHub Releases `.exe` / `.msi` installer; recruit Windows beta testers.
141+
3. **Linux** — AppImage or Flatpak distributed via GitHub Releases.
142+
143+
Collect crash reports using Sentry or a lightweight logging service to catch issues you can't reproduce locally.
144+
145+
---
146+
147+
## Development Workflow
148+
149+
### Working on the `cross-platform-dev` Branch
150+
151+
```bash
152+
git fetch origin
153+
git checkout cross-platform-dev
154+
# Make changes, commit, push
155+
git push origin cross-platform-dev
156+
```
157+
158+
Opening a PR from `cross-platform-dev` → `main` will trigger the prerelease workflow, giving you a build artifact before merging.
159+
160+
### Running CI Builds Without Merging
161+
162+
Trigger the release workflow manually with `workflow_dispatch`:
163+
164+
1. Go to **Actions** → **Build & Release macOS App**.
165+
2. Click **Run workflow**, set **draft** to `true`.
166+
3. GitHub will build and produce a draft release you can download and test.
167+
168+
### Merging Strategy
169+
170+
1. All Windows/Linux work stays on `cross-platform-dev`.
171+
2. When a platform is stable (passes CI, passes beta testing):
172+
- Open a PR from `cross-platform-dev` → `main`.
173+
- The prerelease workflow builds and uploads artifacts automatically.
174+
- After review and merge, the release workflow publishes the new version.
175+
3. Bump `MARKETING_VERSION` in `Jot.xcodeproj/project.pbxproj` before merging to trigger a new release tag.
176+
177+
---
178+
179+
## Project Structure Notes
180+
181+
```
182+
PinStick/
183+
├── Jot.xcodeproj.zip # Xcode project (unzip before building)
184+
├── PinStickApp.swift # App entry point + ContentView
185+
├── Item.swift # Data model
186+
├── Jot.entitlements # macOS sandbox entitlements
187+
├── Contents.json # AppIcon.xcassets icon catalog
188+
├── icon_*.png # App icon assets (all sizes)
189+
├── JotTests.swift # Unit tests
190+
├── JotUITests.swift # UI tests
191+
├── JotUITestsLaunchTests.swift
192+
└── .github/
193+
├── workflows/
194+
│ ├── prerelease.yml # PR prerelease automation
195+
│ └── build-and-release.yml # Main branch release automation
196+
└── copilot-instructions.md # This file
197+
```
198+
199+
### Asset Catalog Icon Sizes (macOS)
200+
201+
| File | Logical Size | Scale |
202+
|---|---|---|
203+
| `icon_16x16.png` | 16×16 | @1x |
204+
| `icon_32x32.png` | 16×16 | @2x |
205+
| `icon_32x32 1.png` | 32×32 | @1x |
206+
| `icon_64x64.png` | 32×32 | @2x |
207+
| `icon_128x128.png` | 128×128 | @1x |
208+
| `icon_256x256.png` | 128×128 | @2x |
209+
| `icon_256x256 1.png` | 256×256 | @1x |
210+
| `icon_512x512.png` | 256×256 | @2x |
211+
| `icon_512x512 1.png` | 512×512 | @1x |
212+
| `icon_1024x1024.png` | 512×512 | @2x |

.github/scripts/extract-version.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
PROJECT_ZIP="${PROJECT_ZIP:-Jot.xcodeproj.zip}"
5+
PROJECT_DIR="Jot.xcodeproj"
6+
TMP_DIR="$(mktemp -d 2>/dev/null || mktemp -d -t jotproj)"
7+
trap 'rm -rf "$TMP_DIR"' EXIT
8+
9+
unzip -o "$PROJECT_ZIP" "$PROJECT_DIR/project.pbxproj" -d "$TMP_DIR" >/dev/null
10+
PBXPROJ="$TMP_DIR/$PROJECT_DIR/project.pbxproj"
11+
12+
VERSION=$(grep -m1 'MARKETING_VERSION = ' "$PBXPROJ" | awk -F ' = ' '{ gsub(/;/,"",$2); print $2; exit }')
13+
if [ -z "$VERSION" ]; then
14+
echo "Could not extract MARKETING_VERSION" >&2
15+
exit 1
16+
fi
17+
18+
echo "v$VERSION"

0 commit comments

Comments
 (0)