mirror of
https://github.com/tiennm99/loto.git
synced 2026-10-13 04:15:09 +00:00
ci: consolidate web and android workflows into one pipeline
Both subprojects ship from the same commit, so ordinary CI is now a single ci.yml; only the tag-driven release stands apart. The web app is built twice per run — once per base path — and every consumer downloads the artifact instead of rebuilding, replacing three redundant base-"" builds on main. Nothing deploys unless the test job is green, and android-release runs the suite before signing (ci.yml does not fire on tags, so it was the only gap). Shared toolchain setup moves into composite actions, which puts the web build and the APK on the same Node version for the first time. The Firebase PR path was still on npm ci against a stale web/package-lock.json that could resolve a different tree than pnpm-lock.yaml; drop the lockfile and the npm path with it. Also: least-privilege permissions widened per job, persist-credentials off on every checkout, concurrency groups that cancel superseded PRs but never a live deploy, npm caching for android, and the Firebase action pinned by commit SHA to match how the release actions were already pinned.
This commit is contained in:
1 parent
dfc9f67e0c
commit
c6c839fd95
17 files changed
+321
-8681
No files matched your search
@@ -1,59 +0,0 @@
|
||||
name: android / build debug
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'web/**'
|
||||
- 'android/**'
|
||||
- '.github/workflows/android-build-debug.yml'
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'web/**'
|
||||
- 'android/**'
|
||||
- '.github/workflows/android-build-debug.yml'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: android
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Set up Node 22
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
with:
|
||||
cache-provider: basic
|
||||
|
||||
- name: Install wrapper deps
|
||||
run: npm ci
|
||||
|
||||
- name: Build web + sync into Android
|
||||
run: npm run build
|
||||
|
||||
- name: Assemble debug APK
|
||||
working-directory: android/android
|
||||
run: ./gradlew :app:assembleDebug
|
||||
|
||||
- name: Upload debug APK
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: app-debug.apk
|
||||
path: android/android/app/build/outputs/apk/debug/*.apk
|
||||
archive: false
|
||||
retention-days: 7
|
||||
@@ -1,3 +1,7 @@
|
||||
# Tag-driven release. Builds standalone rather than consuming ci.yml
|
||||
# artifacts: a tag run has no upstream run to pull from, and a release
|
||||
# should be reproducible from the tagged tree alone.
|
||||
|
||||
name: android / release
|
||||
|
||||
on:
|
||||
@@ -7,40 +11,36 @@ on:
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: android-release-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: android
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node 22
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: '22'
|
||||
- uses: ./.github/actions/setup-web
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
# ci.yml does not run on tags, so this is the only gate before signing.
|
||||
- name: Test web
|
||||
run: pnpm test
|
||||
working-directory: web
|
||||
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
with:
|
||||
cache-provider: basic
|
||||
# Base "" — the APK loads the bundle from the domain root.
|
||||
- name: Build web
|
||||
run: pnpm build
|
||||
working-directory: web
|
||||
|
||||
- name: Install wrapper deps
|
||||
run: npm ci
|
||||
- uses: ./.github/actions/setup-android
|
||||
|
||||
- name: Build web + sync into Android
|
||||
run: npm run build
|
||||
- name: Sync web bundle into the native project
|
||||
run: npm run sync
|
||||
working-directory: android
|
||||
|
||||
- name: Decode keystore
|
||||
env:
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
# One pipeline for both subprojects, because they ship from the same commit.
|
||||
#
|
||||
# The web app is built twice and only twice — once per base path — and every
|
||||
# consumer downloads an artifact instead of rebuilding:
|
||||
#
|
||||
# build (root, base "") -> deploy-firebase, preview-firebase, android-debug
|
||||
# build (gh, base /loto) -> deploy-pages
|
||||
#
|
||||
# Tags are handled by android-release.yml, which builds standalone.
|
||||
|
||||
name: ci
|
||||
|
||||
# Actions' parser rejects YAML anchors, so the two path lists are duplicated
|
||||
# by necessity — keep them identical.
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'web/**'
|
||||
- 'android/**'
|
||||
- '.github/actions/**'
|
||||
- '.github/workflows/ci.yml'
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'web/**'
|
||||
- 'android/**'
|
||||
- '.github/actions/**'
|
||||
- '.github/workflows/ci.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.ref }}
|
||||
# Superseded PRs are safe to kill; a main run may be mid-deploy.
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: ./.github/actions/setup-web
|
||||
- run: pnpm test
|
||||
working-directory: web
|
||||
|
||||
build:
|
||||
# Nothing is built, shipped or signed unless the suite is green.
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# Firebase and the APK serve from a domain root.
|
||||
- profile: root
|
||||
script: build
|
||||
artifact: web-build
|
||||
# GitHub Pages serves under /loto.
|
||||
- profile: gh
|
||||
script: 'build:gh'
|
||||
artifact: web-build-gh
|
||||
name: build (${{ matrix.profile }})
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: ./.github/actions/setup-web
|
||||
- run: pnpm ${{ matrix.script }}
|
||||
working-directory: web
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: web/build
|
||||
# Hand-off within this run only; releases keep their own copies.
|
||||
retention-days: 1
|
||||
|
||||
deploy-pages:
|
||||
if: github.event_name != 'pull_request'
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
# Guards the shared Pages environment against runs of other workflows.
|
||||
concurrency:
|
||||
group: github-pages
|
||||
cancel-in-progress: true
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: web-build-gh
|
||||
path: build
|
||||
- uses: actions/configure-pages@v6
|
||||
- uses: actions/upload-pages-artifact@v5
|
||||
with:
|
||||
path: build
|
||||
- id: deployment
|
||||
uses: actions/deploy-pages@v5
|
||||
|
||||
deploy-firebase:
|
||||
if: github.event_name != 'pull_request'
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: firebase-hosting-live
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
# entryPoint below reads web/firebase.json and web/.firebaserc.
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: web-build
|
||||
# firebase.json declares `public: "build"`, relative to entryPoint.
|
||||
path: web/build
|
||||
- uses: FirebaseExtended/action-hosting-deploy@500ac625ca2dd40cbd15f7659af953801858032a # v0
|
||||
with:
|
||||
repoToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_LOOTOO }}
|
||||
channelId: live
|
||||
projectId: lootoo
|
||||
entryPoint: web
|
||||
|
||||
preview-firebase:
|
||||
# Forks cannot read the service account, so skip rather than fail.
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
checks: write
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: web-build
|
||||
path: web/build
|
||||
- uses: FirebaseExtended/action-hosting-deploy@500ac625ca2dd40cbd15f7659af953801858032a # v0
|
||||
with:
|
||||
repoToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_LOOTOO }}
|
||||
projectId: lootoo
|
||||
entryPoint: web
|
||||
|
||||
android-debug:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: web-build
|
||||
# capacitor.config.json declares `webDir: "../web/build"`.
|
||||
path: web/build
|
||||
- uses: ./.github/actions/setup-android
|
||||
# `npm run build` would rebuild web/; the bundle is already here.
|
||||
- name: Sync web bundle into the native project
|
||||
run: npm run sync
|
||||
working-directory: android
|
||||
- name: Assemble debug APK
|
||||
run: ./gradlew :app:assembleDebug
|
||||
working-directory: android/android
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: app-debug.apk
|
||||
path: android/android/app/build/outputs/apk/debug/*.apk
|
||||
archive: false
|
||||
retention-days: 7
|
||||
@@ -1,51 +0,0 @@
|
||||
name: web / deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'web/**'
|
||||
- '.github/workflows/web-deploy-github-pages.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: github-pages
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: web
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: pnpm/action-setup@v6
|
||||
with:
|
||||
package_json_file: web/package.json
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: pnpm
|
||||
cache-dependency-path: web/pnpm-lock.yaml
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- run: pnpm build:gh
|
||||
- uses: actions/configure-pages@v6
|
||||
- uses: actions/upload-pages-artifact@v5
|
||||
with:
|
||||
path: web/build
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- id: deployment
|
||||
uses: actions/deploy-pages@v5
|
||||
@@ -1,26 +0,0 @@
|
||||
# Originally generated by the Firebase CLI
|
||||
# https://github.com/firebase/firebase-tools
|
||||
# entryPoint points the action at web/, where firebase.json and .firebaserc live.
|
||||
|
||||
name: web / deploy to Firebase Hosting on merge
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'web/**'
|
||||
- '.github/workflows/web-firebase-hosting-merge.yml'
|
||||
jobs:
|
||||
build_and_deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- run: npm ci && npm run build
|
||||
working-directory: web
|
||||
- uses: FirebaseExtended/action-hosting-deploy@v0
|
||||
with:
|
||||
repoToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_LOOTOO }}
|
||||
channelId: live
|
||||
projectId: lootoo
|
||||
entryPoint: web
|
||||
@@ -1,28 +0,0 @@
|
||||
# Originally generated by the Firebase CLI
|
||||
# https://github.com/firebase/firebase-tools
|
||||
# entryPoint points the action at web/, where firebase.json and .firebaserc live.
|
||||
|
||||
name: web / deploy to Firebase Hosting on PR
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'web/**'
|
||||
- '.github/workflows/web-firebase-hosting-pull-request.yml'
|
||||
permissions:
|
||||
checks: write
|
||||
contents: read
|
||||
pull-requests: write
|
||||
jobs:
|
||||
build_and_preview:
|
||||
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- run: npm ci && npm run build
|
||||
working-directory: web
|
||||
- uses: FirebaseExtended/action-hosting-deploy@v0
|
||||
with:
|
||||
repoToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_LOOTOO }}
|
||||
projectId: lootoo
|
||||
entryPoint: web
|
||||
@@ -1,41 +0,0 @@
|
||||
name: web / verify build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'web/**'
|
||||
- '.github/workflows/web-verify-build.yml'
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'web/**'
|
||||
- '.github/workflows/web-verify-build.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: web-verify-build-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: web
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: pnpm/action-setup@v6
|
||||
with:
|
||||
package_json_file: web/package.json
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: pnpm
|
||||
cache-dependency-path: web/pnpm-lock.yaml
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- run: pnpm test
|
||||
- run: pnpm build
|
||||
Reference in new issue
Block a user