Initial Camp Scan ticketing system
Backend (Fastify + TS): FluentForms webhook -> NocoDB row + QR + MailerSend email; PIN auth; scan/lookup/redeem with per-code serialization; reusable QR codes with count-based check-in; admin search. App (Expo, one codebase): Android APK + iPhone PWA. Login, camera scanner (native + web barcode-detector split), green/red overlay with sound + haptics, admin lookup/redeem. Session token persisted per device. Ops: multi-stage Dockerfile serving API + PWA same-origin, compose bound to 127.0.0.1; Forgejo Actions runner + tag-triggered signed APK build for Obtainium. Docs in README.md and INSTALL.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
commit
3397e3e3ec
60 changed files with 14703 additions and 0 deletions
24
ci/set-version.mjs
Normal file
24
ci/set-version.mjs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Set app.json version + Android versionCode from a git tag before prebuild.
|
||||
// Usage: node ci/set-version.mjs v1.2.3
|
||||
// versionName = 1.2.3 ; versionCode = 1*1_000_000 + 2*1_000 + 3 (monotonic,
|
||||
// so Obtainium installs each new release over the previous one).
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
|
||||
const raw = process.argv[2] || "v0.0.0";
|
||||
const m = raw.replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
||||
if (!m) {
|
||||
console.error(`set-version: cannot parse tag "${raw}"`);
|
||||
process.exit(1);
|
||||
}
|
||||
const [, MA, MI, PA] = m.map(Number);
|
||||
const versionName = `${MA}.${MI}.${PA}`;
|
||||
const versionCode = MA * 1_000_000 + MI * 1_000 + PA;
|
||||
|
||||
const path = new URL("../app/app.json", import.meta.url);
|
||||
const cfg = JSON.parse(readFileSync(path, "utf8"));
|
||||
cfg.expo.version = versionName;
|
||||
cfg.expo.android = cfg.expo.android || {};
|
||||
cfg.expo.android.versionCode = versionCode;
|
||||
writeFileSync(path, JSON.stringify(cfg, null, 2) + "\n");
|
||||
|
||||
console.log(`set-version: versionName=${versionName} versionCode=${versionCode}`);
|
||||
30
ci/signing.gradle
Normal file
30
ci/signing.gradle
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Injected at build time with `--init-script` so it survives `expo prebuild`
|
||||
// regenerating android/. Overrides the release signing config to use the
|
||||
// keystore + credentials supplied via environment variables in CI.
|
||||
gradle.projectsLoaded {
|
||||
rootProject.subprojects { sub ->
|
||||
sub.afterEvaluate {
|
||||
if (sub.plugins.hasPlugin('com.android.application')) {
|
||||
def storeFilePath = System.getenv('CAMPSCAN_STORE_FILE')
|
||||
if (storeFilePath == null || storeFilePath.isEmpty()) {
|
||||
return
|
||||
}
|
||||
sub.android {
|
||||
signingConfigs {
|
||||
campscanRelease {
|
||||
storeFile file(storeFilePath)
|
||||
storePassword System.getenv('CAMPSCAN_STORE_PASSWORD')
|
||||
keyAlias System.getenv('CAMPSCAN_KEY_ALIAS')
|
||||
keyPassword System.getenv('CAMPSCAN_KEY_PASSWORD')
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig signingConfigs.campscanRelease
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue