From 896f9149f13a4b529a2393190bc14a82a5a3d913 Mon Sep 17 00:00:00 2001 From: Space-Banane Date: Sat, 4 Jul 2026 19:34:22 +0200 Subject: [PATCH] Set up Expo OTA updates and CI workflows --- .eas/workflows/build-android.yml | 22 ++++++++ .eas/workflows/publish-updates.yml | 57 ++++++++++++++++++++ app.json | 6 +++ eas.json | 3 ++ package-lock.json | 83 ++++++++++++++++++++++++++++++ package.json | 7 ++- 6 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 .eas/workflows/build-android.yml create mode 100644 .eas/workflows/publish-updates.yml diff --git a/.eas/workflows/build-android.yml b/.eas/workflows/build-android.yml new file mode 100644 index 0000000..a958a84 --- /dev/null +++ b/.eas/workflows/build-android.yml @@ -0,0 +1,22 @@ +name: Build Android APK + +on: + workflow_dispatch: + inputs: + profile: + type: choice + description: EAS build profile to use. + default: production + options: + - preview + - production + +jobs: + build_android: + name: Build Android APK + type: build + environment: ${{ inputs.profile }} + params: + platform: android + profile: ${{ inputs.profile }} + message: Android ${{ inputs.profile }} APK from ${{ github.ref_name }} diff --git a/.eas/workflows/publish-updates.yml b/.eas/workflows/publish-updates.yml new file mode 100644 index 0000000..5f807f4 --- /dev/null +++ b/.eas/workflows/publish-updates.yml @@ -0,0 +1,57 @@ +name: Publish OTA updates + +on: + push: + branches: ['main'] + paths: + - 'app/**' + - 'components/**' + - 'hooks/**' + - 'lib/**' + - 'types/**' + - 'assets/**' + - 'App.tsx' + - 'index.ts' + - 'global.css' + - 'tailwind.config.js' + - 'babel.config.js' + - 'metro.config.js' + workflow_dispatch: + inputs: + channel: + type: choice + description: Update channel to publish. + default: production + options: + - preview + - production + environment: + type: choice + description: EAS environment to use for the update job. + default: production + options: + - preview + - production + message: + description: Optional update message override. + required: false + +jobs: + publish_main: + if: ${{ github.event_name == 'push' }} + name: Publish production update + type: update + environment: production + params: + channel: production + platform: all + + publish_manual: + if: ${{ github.event_name == 'workflow_dispatch' }} + name: Publish selected update + type: update + environment: ${{ inputs.environment }} + params: + channel: ${{ inputs.channel }} + message: ${{ inputs.message }} + platform: all diff --git a/app.json b/app.json index 48e337b..205c738 100644 --- a/app.json +++ b/app.json @@ -5,6 +5,12 @@ "description": "Monitor Codex CLI and Claude.ai usage limits, resets, and credits at a glance.", "scheme": "codexbar", "version": "1.0.0", + "runtimeVersion": { + "policy": "appVersion" + }, + "updates": { + "url": "https://u.expo.dev/9196c5ee-4c6e-4229-9a99-54b50afe38e8" + }, "orientation": "portrait", "icon": "./assets/icon.png", "backgroundColor": "#090D11", diff --git a/eas.json b/eas.json index 7d23ada..4f71066 100644 --- a/eas.json +++ b/eas.json @@ -5,12 +5,15 @@ }, "build": { "preview": { + "channel": "preview", "distribution": "internal", "android": { "buildType": "apk" } }, "production": { + "channel": "production", + "distribution": "internal", "android": { "buildType": "apk" } diff --git a/package-lock.json b/package-lock.json index 0a57e3e..3d6d179 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "expo-splash-screen": "~56.0.10", "expo-status-bar": "~56.0.4", "expo-system-ui": "~56.0.5", + "expo-updates": "~56.0.21", "nativewind": "^4.2.6", "react": "19.2.3", "react-dom": "^19.2.3", @@ -3958,6 +3959,12 @@ "expo": "*" } }, + "node_modules/expo-eas-client": { + "version": "56.0.1", + "resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-56.0.1.tgz", + "integrity": "sha512-r8h0ZIExacCrSRgY+ARfhMvFqosLHLJt1L7jyhvabfr1DN/ZDKDsYbovss2tzkpEUZGxZ3BPcB5epCwUsBBdOA==", + "license": "MIT" + }, "node_modules/expo-file-system": { "version": "56.0.8", "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-56.0.8.tgz", @@ -3994,6 +4001,12 @@ "react-native": "*" } }, + "node_modules/expo-json-utils": { + "version": "56.0.0", + "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-56.0.0.tgz", + "integrity": "sha512-lUqyv9aIGDbYTQ5Nux2FnH2/Dz0w5uJ8Pr080eS0StXi2jr5OmuMNErpzUnpfnYOU55xKotd4AHv68PfV/ludg==", + "license": "MIT" + }, "node_modules/expo-keep-awake": { "version": "56.0.3", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-56.0.3.tgz", @@ -4019,6 +4032,18 @@ "react-native": "*" } }, + "node_modules/expo-manifests": { + "version": "56.0.4", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-56.0.4.tgz", + "integrity": "sha512-Fokawl2UkiExIF0bqGoblRFA8lYpROVD+EpvDwSW4LgqQyPwNua1gLSgHZjdl5GsVugfRMMWE3LHaibDyX93hw==", + "license": "MIT", + "dependencies": { + "expo-json-utils": "~56.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-modules-autolinking": { "version": "56.0.18", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-56.0.18.tgz", @@ -4206,6 +4231,12 @@ "react-native": "*" } }, + "node_modules/expo-structured-headers": { + "version": "56.0.0", + "resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-56.0.0.tgz", + "integrity": "sha512-Yv4x+SQxNnMQm4nu8NFfzx197YaDhdYH2N0u7tGErwWTmH9Tm1SAhqo7bLbBWLC9kf7W+kdzTshLU9rTiCXWGw==", + "license": "MIT" + }, "node_modules/expo-symbols": { "version": "56.0.6", "resolved": "https://registry.npmjs.org/expo-symbols/-/expo-symbols-56.0.6.tgz", @@ -4242,6 +4273,58 @@ } } }, + "node_modules/expo-updates": { + "version": "56.0.21", + "resolved": "https://registry.npmjs.org/expo-updates/-/expo-updates-56.0.21.tgz", + "integrity": "sha512-7kYS2/ra9Lg4xBG6Fadcq/YR8DngdCeBVc0lQeHvqH/dZHL2N0bJRu0y4utJd9tpIzQtNCmceGu1SmGZVT57/Q==", + "license": "MIT", + "dependencies": { + "@expo/code-signing-certificates": "^0.0.6", + "@expo/plist": "^0.7.0", + "@expo/spawn-async": "^1.8.0", + "arg": "^4.1.0", + "chalk": "^4.1.2", + "debug": "^4.3.4", + "expo-eas-client": "~56.0.0", + "expo-manifests": "~56.0.4", + "expo-structured-headers": "~56.0.0", + "expo-updates-interface": "~56.0.1", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "ignore": "^5.3.1", + "nullthrows": "^1.1.1", + "resolve-from": "^5.0.0" + }, + "bin": { + "expo-updates": "bin/cli.js" + }, + "peerDependencies": { + "expo": "*", + "expo-dev-client": "*", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "expo-dev-client": { + "optional": true + } + } + }, + "node_modules/expo-updates-interface": { + "version": "56.0.2", + "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-56.0.2.tgz", + "integrity": "sha512-eWTwSZ9y8vrULG2oBn2TQSSIwBGSq/TxGJ3jY6tuVS2FWH/ASRIiKs3zkUZTRoC3ZuV2alz0mUClYV7nNrFx8g==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-updates/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "license": "MIT" + }, "node_modules/expo/node_modules/@expo/cli": { "version": "56.1.18", "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-56.1.18.tgz", diff --git a/package.json b/package.json index 8d943d6..7d92963 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "expo-splash-screen": "~56.0.10", "expo-status-bar": "~56.0.4", "expo-system-ui": "~56.0.5", + "expo-updates": "~56.0.21", "nativewind": "^4.2.6", "react": "19.2.3", "react-dom": "^19.2.3", @@ -37,7 +38,11 @@ "start": "expo start", "android": "expo start --android", "ios": "expo start --ios", - "web": "expo start --web" + "web": "expo start --web", + "update:preview": "eas update --channel preview --environment preview", + "update:production": "eas update --channel production --environment production", + "build:android:preview": "eas build --platform android --profile preview --non-interactive", + "build:android:production": "eas build --platform android --profile production --non-interactive" }, "private": true }