Skip to content

Commit dcec8d0

Browse files
authored
Merge pull request #1 from torkinos/main
Initial Release
2 parents af31f44 + e5933df commit dcec8d0

666 files changed

Lines changed: 63002 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/pull_request_template.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[Ticket ID](url)
2+
3+
### Requirements
4+
<!-- List the requirements for this PR -->
5+
6+
### Changes
7+
<!-- Summarize the changes introduced in this PR -->
8+
9+
### Testing Notes
10+
<!-- How did you test it? -->
11+
12+
### Things reviewers should pay attention to
13+
<!-- Highlight anything specific you want reviewers to focus on -->
14+
15+
### Screenshots/Recordings
16+
<!-- Add screenshots or screen recordings if applicable -->
17+
18+
### dependencies
19+
<!-- List any dependent work items or PRs -->
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
name: Build Appling
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- dev
8+
workflow_dispatch:
9+
inputs:
10+
tag:
11+
description: 'Version tag'
12+
required: true
13+
type: string
14+
15+
jobs:
16+
version:
17+
runs-on: ubuntu-22.04
18+
outputs:
19+
version: ${{ steps.meta.outputs.VERSION }}
20+
strategy:
21+
matrix:
22+
arch:
23+
- x64
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- name: Read & validate version
28+
id: meta
29+
run: |
30+
set -euo pipefail
31+
VERSION=$(jq -r '.version' package.json)
32+
echo "VERSION=$VERSION"
33+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
34+
echo "❌ Error: package.json version ('$VERSION') is not semantic versioning (MAJOR.MINOR.PATCH)."
35+
exit 1
36+
fi
37+
TAG="v$VERSION"
38+
echo "TAG=$TAG"
39+
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
40+
echo "TAG=$TAG" >> "$GITHUB_OUTPUT"
41+
42+
linux:
43+
runs-on: ubuntu-22.04
44+
needs: [version]
45+
strategy:
46+
matrix:
47+
arch:
48+
- x64
49+
defaults:
50+
run:
51+
working-directory: ./appling
52+
env:
53+
SLACK_WEBHOOK_URL_PATH: ${{ secrets.SLACK_WEBHOOK_URL_PATH }}
54+
GOOGLE_FORM_KEY: ${{ secrets.GOOGLE_FORM_KEY }}
55+
GOOGLE_FORM_MAPPING_TIMESTAMP: ${{ secrets.GOOGLE_FORM_MAPPING_TIMESTAMP }}
56+
GOOGLE_FORM_MAPPING_TOPIC: ${{ secrets.GOOGLE_FORM_MAPPING_TOPIC }}
57+
GOOGLE_FORM_MAPPING_APP: ${{ secrets.GOOGLE_FORM_MAPPING_APP }}
58+
GOOGLE_FORM_MAPPING_OPERATING_SYSTEM: ${{ secrets.GOOGLE_FORM_MAPPING_OPERATING_SYSTEM }}
59+
GOOGLE_FORM_MAPPING_DEVICE_MODEL: ${{ secrets.GOOGLE_FORM_MAPPING_DEVICE_MODEL }}
60+
GOOGLE_FORM_MAPPING_MESSAGE: ${{ secrets.GOOGLE_FORM_MAPPING_MESSAGE }}
61+
GOOGLE_FORM_MAPPING_APP_VERSION: ${{ secrets.GOOGLE_FORM_MAPPING_APP_VERSION }}
62+
TEST_SLACK_WEBHOOK_URL_PATH: ${{ secrets.TEST_SLACK_WEBHOOK_URL_PATH }}
63+
TEST_GOOGLE_FORM_KEY: ${{ secrets.TEST_GOOGLE_FORM_KEY }}
64+
TEST_GOOGLE_FORM_MAPPING_TIMESTAMP: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_TIMESTAMP }}
65+
TEST_GOOGLE_FORM_MAPPING_TOPIC: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_TOPIC }}
66+
TEST_GOOGLE_FORM_MAPPING_APP: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_APP }}
67+
TEST_GOOGLE_FORM_MAPPING_OPERATING_SYSTEM: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_OPERATING_SYSTEM }}
68+
TEST_GOOGLE_FORM_MAPPING_DEVICE_MODEL: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_DEVICE_MODEL }}
69+
TEST_GOOGLE_FORM_MAPPING_MESSAGE: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_MESSAGE }}
70+
TEST_GOOGLE_FORM_MAPPING_APP_VERSION: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_APP_VERSION }}
71+
steps:
72+
- uses: actions/checkout@v4
73+
74+
- uses: actions/setup-node@v4
75+
with:
76+
node-version: 20
77+
registry-url: 'https://npm.pkg.github.com'
78+
scope: '@tetherto'
79+
80+
- name: Install dependencies
81+
run: |
82+
sudo apt-get update
83+
sudo apt-get install -y curl ca-certificates build-essential git libgtk-4-dev pkg-config fuse file
84+
# sudo apt-get install -y clang pkg-config libgtk-4-dev clang-tools fuse file
85+
wget https://apt.llvm.org/llvm.sh
86+
chmod +x llvm.sh
87+
sudo ./llvm.sh 20
88+
npm install --global bare-make
89+
npm install --install-links --legacy-peer-deps
90+
env:
91+
NODE_AUTH_TOKEN: ${{ secrets.PAT_TOKEN }}
92+
93+
- name: Build Linux AppImage
94+
run: |
95+
bare-make generate --platform linux --arch ${{ matrix.arch }}
96+
bare-make build
97+
98+
- name: Find AppImage file
99+
id: find_file
100+
run: |
101+
APPIMAGE_PATH=$(find $GITHUB_WORKSPACE -name "*.AppImage" -type f | head -n 1)
102+
echo "APPIMAGE_PATH=$APPIMAGE_PATH" >> $GITHUB_OUTPUT
103+
echo "Found AppImage at: $APPIMAGE_PATH"
104+
105+
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
106+
echo "TIMESTAMP=$TIMESTAMP" >> $GITHUB_OUTPUT
107+
108+
- uses: actions/upload-artifact@v4
109+
if: ${{ steps.find_file.outputs.APPIMAGE_PATH != '' }}
110+
with:
111+
name: PearPass-Desktop-Linux-${{ matrix.arch }}-v${{ needs.version.outputs.version }}.AppImage
112+
path: "${{ steps.find_file.outputs.APPIMAGE_PATH }}"
113+
114+
macos:
115+
runs-on: macos-14
116+
needs: [version]
117+
strategy:
118+
matrix:
119+
arch:
120+
- x64
121+
- arm64
122+
defaults:
123+
run:
124+
working-directory: ./appling
125+
env:
126+
SLACK_WEBHOOK_URL_PATH: ${{ secrets.SLACK_WEBHOOK_URL_PATH }}
127+
GOOGLE_FORM_KEY: ${{ secrets.GOOGLE_FORM_KEY }}
128+
GOOGLE_FORM_MAPPING_TIMESTAMP: ${{ secrets.GOOGLE_FORM_MAPPING_TIMESTAMP }}
129+
GOOGLE_FORM_MAPPING_TOPIC: ${{ secrets.GOOGLE_FORM_MAPPING_TOPIC }}
130+
GOOGLE_FORM_MAPPING_APP: ${{ secrets.GOOGLE_FORM_MAPPING_APP }}
131+
GOOGLE_FORM_MAPPING_OPERATING_SYSTEM: ${{ secrets.GOOGLE_FORM_MAPPING_OPERATING_SYSTEM }}
132+
GOOGLE_FORM_MAPPING_DEVICE_MODEL: ${{ secrets.GOOGLE_FORM_MAPPING_DEVICE_MODEL }}
133+
GOOGLE_FORM_MAPPING_MESSAGE: ${{ secrets.GOOGLE_FORM_MAPPING_MESSAGE }}
134+
GOOGLE_FORM_MAPPING_APP_VERSION: ${{ secrets.GOOGLE_FORM_MAPPING_APP_VERSION }}
135+
TEST_SLACK_WEBHOOK_URL_PATH: ${{ secrets.TEST_SLACK_WEBHOOK_URL_PATH }}
136+
TEST_GOOGLE_FORM_KEY: ${{ secrets.TEST_GOOGLE_FORM_KEY }}
137+
TEST_GOOGLE_FORM_MAPPING_TIMESTAMP: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_TIMESTAMP }}
138+
TEST_GOOGLE_FORM_MAPPING_TOPIC: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_TOPIC }}
139+
TEST_GOOGLE_FORM_MAPPING_APP: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_APP }}
140+
TEST_GOOGLE_FORM_MAPPING_OPERATING_SYSTEM: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_OPERATING_SYSTEM }}
141+
TEST_GOOGLE_FORM_MAPPING_DEVICE_MODEL: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_DEVICE_MODEL }}
142+
TEST_GOOGLE_FORM_MAPPING_MESSAGE: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_MESSAGE }}
143+
TEST_GOOGLE_FORM_MAPPING_APP_VERSION: ${{ secrets.TEST_GOOGLE_FORM_MAPPING_APP_VERSION }}
144+
steps:
145+
- uses: actions/checkout@v4
146+
147+
- uses: actions/setup-node@v4
148+
with:
149+
node-version: 20
150+
registry-url: 'https://npm.pkg.github.com'
151+
scope: '@tetherto'
152+
153+
- name: Install dependencies
154+
run: |
155+
npm install --global bare-make
156+
npm install --install-links --legacy-peer-deps
157+
env:
158+
NODE_AUTH_TOKEN: ${{ secrets.PAT_TOKEN }}
159+
160+
- name: Install the Apple certificate and provisioning profile
161+
env:
162+
BUILD_CERTIFICATE_BASE64: ${{ secrets.APPLE_DISTRIBUTION_CERTIFICATE }}
163+
P12_PASSWORD: ${{ secrets.APPLE_P12_PASSWORD }}
164+
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.APPLE_PROVISIONING_PROFILE }}
165+
KEYCHAIN_PASSWORD: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
166+
APIKEY_BASE64: ${{ secrets.APPLE_APIKEY }}
167+
run: |
168+
# create variables
169+
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
170+
PP_PATH=$RUNNER_TEMP/build_pp.provisionprofile
171+
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
172+
APIKEY_PATH=$RUNNER_TEMP/AuthKey.p8
173+
174+
# import certificate and provisioning profile from secrets
175+
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
176+
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
177+
echo -n "$APIKEY_BASE64" | base64 --decode -o $APIKEY_PATH
178+
179+
# create temporary keychain
180+
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
181+
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
182+
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
183+
184+
# import certificate to keychain
185+
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
186+
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
187+
security list-keychain -d user -s $KEYCHAIN_PATH
188+
189+
# add notarytool credentials
190+
xcrun notarytool store-credentials "pearpass" --key "$APIKEY_PATH" --key-id S3AG2UXSC5 --issuer 2067dae8-140d-4016-9a2b-d6ea80a20708
191+
192+
# apply provisioning profile
193+
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
194+
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
195+
196+
- name: Build macOS app
197+
run: |
198+
bare-make generate --platform darwin --arch ${{ matrix.arch }}
199+
bare-make build
200+
201+
- name: Find App file
202+
id: find_file
203+
run: |
204+
# find the .app bundle (it's a directory)
205+
APPIMAGE_PATH=$(find "$GITHUB_WORKSPACE" -name "*.app" -type d | head -n 1)
206+
echo "APPIMAGE_PATH=$APPIMAGE_PATH" >> $GITHUB_OUTPUT
207+
echo "Found app at: $APPIMAGE_PATH"
208+
209+
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
210+
echo "TIMESTAMP=$TIMESTAMP" >> $GITHUB_OUTPUT
211+
212+
- name: Create DMG and notarize
213+
id: create_dmg
214+
if: ${{ steps.find_file.outputs.APPIMAGE_PATH != '' }}
215+
run: |
216+
npm install --global create-dmg
217+
create-dmg "${{ steps.find_file.outputs.APPIMAGE_PATH }}" --identity=959D2C8BB8323AEF9C2367ACA2F854AE4D7DE458 --no-version-in-filename
218+
DMG=$(find "$GITHUB_WORKSPACE" -name "*.dmg" -type d | head -n 1)
219+
echo "DMG=$DMG" >> $GITHUB_OUTPUT
220+
echo "Found dmg at: $DMG"
221+
222+
- name: Notarize DMG
223+
run: |
224+
xcrun notarytool submit "Pearpass.dmg" --keychain-profile "pearpass" --wait
225+
226+
- name: Staple DMG
227+
run: |
228+
xcrun stapler staple "Pearpass.dmg"
229+
xcrun stapler validate "Pearpass.dmg"
230+
231+
- uses: actions/upload-artifact@v4
232+
if: ${{ steps.find_file.outputs.APPIMAGE_PATH != '' }}
233+
with:
234+
name: PearPass-Desktop-MacOS-${{ matrix.arch }}-v${{ needs.version.outputs.version }}.dmg
235+
path: "${{ github.workspace }}/appling/Pearpass.dmg"
236+
237+
- name: Clean up keychain and provisioning profile
238+
if: ${{ always() }}
239+
run: |
240+
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
241+
rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.provisionprofile
242+
243+
release:
244+
runs-on: ubuntu-latest
245+
needs: [version, linux, macos]
246+
if: github.ref == 'refs/heads/main'
247+
steps:
248+
- name: Download artifacts
249+
uses: actions/download-artifact@v5
250+
with:
251+
path: artifacts/
252+
merge-multiple: true
253+
254+
- name: Create Release
255+
uses: softprops/action-gh-release@v2
256+
with:
257+
tag_name: v${{ needs.version.outputs.version }}
258+
name: PearPass-Desktop-v${{ needs.version.outputs.version }}
259+
files: artifacts/**
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Publish App on Merge to Test
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
workflow_dispatch:
8+
9+
env:
10+
CHANNEL_LINK: "pear://ahdgc4xremb3zxnwfth34fun6yxy1jy6az71uun3bh6sy5z4ebwy"
11+
12+
permissions:
13+
contents: read
14+
packages: read
15+
16+
jobs:
17+
publish-worker:
18+
runs-on: ["self-hosted", "Linux", "large"]
19+
steps:
20+
- uses: actions/checkout@v4
21+
- name: Checkout submodules
22+
run: |
23+
git submodule deinit --force .
24+
git submodule update --init --recursive
25+
- name: Setup Node.js
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: "22.x"
29+
- uses: actions/setup-node@v4
30+
with:
31+
registry-url: "https://npm.pkg.github.com"
32+
scope: "@tetherto"
33+
- name: Install worker dependencies
34+
run: |
35+
npm install --install-links
36+
env:
37+
NODE_AUTH_TOKEN: ${{ secrets.NOXTTON_BOT_PAT }}
38+
- name: Extract translations
39+
run: |
40+
npm run lingui:extract
41+
npm run lingui:compile
42+
# - name: Prune dev dependencies
43+
# run: npm prune --omit=dev
44+
- name: "Stage to channel"
45+
run: |
46+
echo "CHANNEL_LINK: ${CHANNEL_LINK}"
47+
pear stage --ignore .git --no-ask ${CHANNEL_LINK} .
48+
- name: "Release latest version"
49+
run: |
50+
pear release ${CHANNEL_LINK}

.github/workflows/merge-main.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Publish App on Merge to Live
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
env:
10+
CHANNEL_LINK: "pear://8mzabhx3kbpq88eqy7wiuu1csjqqkry19c3di8nixu5rgt6cmupy"
11+
12+
permissions:
13+
contents: read
14+
packages: read
15+
16+
jobs:
17+
publish-worker:
18+
runs-on: ["self-hosted", "Linux", "large"]
19+
steps:
20+
- uses: actions/checkout@v4
21+
- name: Checkout submodules
22+
run: |
23+
git submodule deinit --force .
24+
git submodule update --init --recursive
25+
- name: Setup Node.js
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: "22.x"
29+
- uses: actions/setup-node@v4
30+
with:
31+
registry-url: "https://npm.pkg.github.com"
32+
scope: "@tetherto"
33+
- name: Install worker dependencies
34+
run: |
35+
npm install --install-links
36+
env:
37+
NODE_AUTH_TOKEN: ${{ secrets.NOXTTON_BOT_PAT }}
38+
- name: Extract translations
39+
run: |
40+
npm run lingui:extract
41+
npm run lingui:compile
42+
# - name: Prune dev dependencies
43+
# run: npm prune --omit=dev
44+
- name: "Stage to channel"
45+
run: |
46+
echo "CHANNEL_LINK: ${CHANNEL_LINK}"
47+
pear stage --ignore .git --no-ask ${CHANNEL_LINK} .
48+
- name: "Release latest version"
49+
run: |
50+
pear release ${CHANNEL_LINK}

0 commit comments

Comments
 (0)