Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/expo-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,38 @@ jobs:
run: pnpm install --frozen-lockfile
- name: TypeScript type check
run: npx tsc --noEmit

build:
runs-on: ubuntu-latest
needs: [lint, format, typecheck]
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 10.12.1
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Ensure EAS CLI available
run: pnpm dlx eas-cli@latest --version
# No explicit login needed, Expo CLI uses EXPO_TOKEN env automatically
- name: Build Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build:download --platform android --profile preview --latest --path ./app.apk
Comment on lines +92 to +99
Copy link

Copilot AI Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The EAS CLI version is not pinned, using '@latest' which could lead to unexpected behavior if breaking changes are introduced. Consider pinning to a specific version for reproducible builds.

Suggested change
run: pnpm dlx eas-cli@latest --version
# No explicit login needed, Expo CLI uses EXPO_TOKEN env automatically
- name: Build Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build:download --platform android --profile preview --latest --path ./app.apk
run: pnpm dlx eas-cli@6.3.0 --version
# No explicit login needed, Expo CLI uses EXPO_TOKEN env automatically
- name: Build Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@6.3.0 build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@6.3.0 build:download --platform android --profile preview --latest --path ./app.apk

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +99
Copy link

Copilot AI Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The EAS CLI version is not pinned, using '@latest' which could lead to unexpected behavior if breaking changes are introduced. Consider pinning to a specific version for reproducible builds.

Suggested change
run: pnpm dlx eas-cli@latest --version
# No explicit login needed, Expo CLI uses EXPO_TOKEN env automatically
- name: Build Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build:download --platform android --profile preview --latest --path ./app.apk
run: pnpm dlx eas-cli@6.3.0 --version
# No explicit login needed, Expo CLI uses EXPO_TOKEN env automatically
- name: Build Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@6.3.0 build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@6.3.0 build:download --platform android --profile preview --latest --path ./app.apk

Copilot uses AI. Check for mistakes.
# ...existing code...
- name: Upload Android artifact
if: env.EXPO_TOKEN != ''
Comment on lines +95 to +102
Copy link

Copilot AI Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition 'env.EXPO_TOKEN != ''' is repeated three times. Consider using a job-level condition or extracting this to a reusable condition to reduce duplication.

Suggested change
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build:download --platform android --profile preview --latest --path ./app.apk
# ...existing code...
- name: Upload Android artifact
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
run: pnpm dlx eas-cli@latest build:download --platform android --profile preview --latest --path ./app.apk
# ...existing code...
- name: Upload Android artifact

Copilot uses AI. Check for mistakes.
Comment on lines +95 to +102
Copy link

Copilot AI Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition 'env.EXPO_TOKEN != ''' is repeated three times. Consider using a job-level condition or extracting this to a reusable condition to reduce duplication.

Suggested change
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build:download --platform android --profile preview --latest --path ./app.apk
# ...existing code...
- name: Upload Android artifact
if: env.EXPO_TOKEN != ''
if: env.HAS_EXPO_TOKEN == 'true'
run: pnpm dlx eas-cli@latest build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
if: env.HAS_EXPO_TOKEN == 'true'
run: pnpm dlx eas-cli@latest build:download --platform android --profile preview --latest --path ./app.apk
# ...existing code...
- name: Upload Android artifact
if: env.HAS_EXPO_TOKEN == 'true'

Copilot uses AI. Check for mistakes.
Comment on lines +95 to +102
Copy link

Copilot AI Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition 'env.EXPO_TOKEN != ''' is repeated three times. Consider using a job-level condition or extracting this to a reusable condition to reduce duplication.

Suggested change
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build:download --platform android --profile preview --latest --path ./app.apk
# ...existing code...
- name: Upload Android artifact
if: env.EXPO_TOKEN != ''
run: pnpm dlx eas-cli@latest build --platform android --non-interactive --profile preview --clear-cache --wait
- name: Download Android APK
run: pnpm dlx eas-cli@latest build:download --platform android --profile preview --latest --path ./app.apk
# ...existing code...
- name: Upload Android artifact

Copilot uses AI. Check for mistakes.
uses: actions/upload-artifact@v4
with:
name: android-apk
path: ./app.apk
Comment on lines +99 to +106
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid --latest; tie download to the build you just triggered

--latest can fetch an unrelated artifact from another commit/branch. The previous diff captures BUILD_ID and downloads that exact build.

🤖 Prompt for AI Agents
.github/workflows/expo-build.yml lines 99-106: the workflow currently uses
`--latest` when running `eas-cli build:download`, which can retrieve an
unrelated artifact; change the command to download the exact build by using the
BUILD_ID captured earlier (e.g., replace `--latest` with `--id ${{ env.BUILD_ID
}}` or the equivalent environment variable you set), keeping the platform,
profile and path flags intact so the download step deterministically fetches the
build you just triggered.

3 changes: 2 additions & 1 deletion app.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
"resizeMode": "contain",
"backgroundColor": "#ffffff"
}
]
],
"./app.plugin.js"
],
"experiments": {
"typedRoutes": true
Expand Down
64 changes: 64 additions & 0 deletions app.plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Inject core-splashscreen dependency to fix Android resource linking errors for Theme.SplashScreen
// This runs during EAS prebuild and modifies android/app/build.gradle
const {
withAppBuildGradle,
createRunOncePlugin,
WarningAggregator,
} = require("@expo/config-plugins");

const DEP_LINE = 'implementation("androidx.core:core-splashscreen:1.0.1")';
const EXPO_AGG_LINE = 'implementation(project(":expo"))';

function ensureDependency(contents) {
// If gradle file isn't available during introspection, just return as-is.
if (typeof contents !== "string") return contents;
const hasDepsBlock = /dependencies\s*\{/m.test(contents);
if (!hasDepsBlock) return contents;

let updated = contents;
// Ensure the :expo aggregator project is present so expo.* classes resolve
if (!updated.includes(EXPO_AGG_LINE)) {
updated = updated.replace(
/dependencies\s*\{/m,
(match) => `${match}\n ${EXPO_AGG_LINE}`,
);
}
// Ensure the splashscreen dependency is present
if (!updated.includes(DEP_LINE)) {
updated = updated.replace(
/dependencies\s*\{/m,
(match) => `${match}\n ${DEP_LINE}`,
);
}

return updated;
}

const withCoreSplashscreenDependency = (config) =>
withAppBuildGradle(config, (config) => {
try {
const updated = ensureDependency(config.modResults?.contents);
if (typeof updated === "string") {
config.modResults.contents = updated;
} else {
// During introspection (e.g., EAS Read app config) the file may not exist yet.
WarningAggregator.addWarningAndroid(
"core-splashscreen",
"Skipped adding androidx.core:core-splashscreen; app/build.gradle not available during introspection.",
);
}
} catch (e) {
WarningAggregator.addWarningAndroid(
"core-splashscreen",
`Failed to add androidx.core:core-splashscreen dependency: ${e?.message ?? e}`,
);
}
return config;
});

// module exp
module.exports = createRunOncePlugin(
withCoreSplashscreenDependency,
"with-core-splashscreen-dependency",
"1.0.0",
);
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@expo/config-plugins": "^7.9.2",
"@types/jest": "^29.5.12",
"@types/react": "~19.0.14",
"@types/react-test-renderer": "^18.3.0",
Expand Down
113 changes: 113 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading