mirror of
https://github.com/chenasraf/pantry-flutter.git
synced 2026-05-17 17:28:03 +00:00
322 lines
9.7 KiB
YAML
322 lines
9.7 KiB
YAML
name: CI/CD
|
|
|
|
on:
|
|
push:
|
|
branches: [master]
|
|
pull_request:
|
|
branches: [master]
|
|
|
|
permissions:
|
|
contents: write
|
|
pull-requests: write
|
|
|
|
jobs:
|
|
lint:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@v2
|
|
with:
|
|
channel: 'stable'
|
|
cache: true
|
|
|
|
- name: Cache pub dependencies
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.pub-cache
|
|
key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
|
|
restore-keys: pub-${{ runner.os }}-
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get
|
|
|
|
- name: Stub .env
|
|
run: cp .env.example .env
|
|
|
|
- name: Verify formatting
|
|
run: dart format --output=none --set-exit-if-changed .
|
|
|
|
- name: Analyze project source
|
|
run: flutter analyze --no-fatal-infos
|
|
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@v2
|
|
with:
|
|
channel: 'stable'
|
|
cache: true
|
|
|
|
- name: Cache pub dependencies
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.pub-cache
|
|
key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
|
|
restore-keys: pub-${{ runner.os }}-
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get
|
|
|
|
- name: Stub .env
|
|
run: cp .env.example .env
|
|
|
|
- name: Run tests
|
|
run: flutter test --coverage --dart-define-from-file=.env
|
|
|
|
- name: Upload coverage
|
|
uses: codecov/codecov-action@v4
|
|
with:
|
|
files: coverage/lcov.info
|
|
fail_ci_if_error: false
|
|
|
|
release-please:
|
|
needs: [lint, test]
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
release_created: ${{ steps.release.outputs.release_created }}
|
|
tag_name: ${{ steps.release.outputs.tag_name }}
|
|
version: ${{ steps.release.outputs.version }}
|
|
|
|
steps:
|
|
- name: Release Please
|
|
id: release
|
|
uses: googleapis/release-please-action@v4
|
|
with:
|
|
release-type: dart
|
|
|
|
- name: Update fastlane changelog on release PR
|
|
if: ${{ steps.release.outputs.pr && !steps.release.outputs.release_created }}
|
|
env:
|
|
PR_JSON: ${{ steps.release.outputs.pr }}
|
|
run: |
|
|
PR_BRANCH=$(echo "$PR_JSON" | jq -r .headBranchName)
|
|
git clone --depth=5 --branch "$PR_BRANCH" \
|
|
https://x-access-token:${{ github.token }}@github.com/${{ github.repository }}.git _pr
|
|
cd _pr
|
|
|
|
VERSION_LINE=$(grep '^version:' pubspec.yaml)
|
|
VERSION=$(echo "$VERSION_LINE" | sed 's/version: *//;s/+.*//')
|
|
CODE=$(echo "$VERSION_LINE" | sed 's/.*+//')
|
|
OUT_DIR="fastlane/metadata/android/en-US/changelogs"
|
|
OUT_FILE="$OUT_DIR/$CODE.txt"
|
|
|
|
mkdir -p "$OUT_DIR"
|
|
|
|
NOTES=$(awk "
|
|
/^## \\[${VERSION//./\\.}\\]/ { found=1; next }
|
|
/^## / { if (found) exit }
|
|
found { print }
|
|
" CHANGELOG.md)
|
|
|
|
NOTES=$(echo "$NOTES" \
|
|
| sed -E 's/ *\(\[[0-9a-f]+\]\([^)]+\)\)//g' \
|
|
| sed -E 's/^\* \*\*[^*]+:\*\* */- /; s/^\* /- /' \
|
|
| sed 's/^### //' \
|
|
| sed '/^[[:space:]]*$/d')
|
|
|
|
NOTES=$(echo "$NOTES" | sed -e '/./,$!d' -e :a -e '/^\n*$/{$d;N;ba;}')
|
|
[ -z "$NOTES" ] && NOTES="Release $VERSION"
|
|
|
|
MAX=500
|
|
TRAILER=$'\n\n… see full notes on GitHub.'
|
|
if [ ${#NOTES} -gt $MAX ]; then
|
|
BUDGET=$((MAX - ${#TRAILER}))
|
|
NOTES="${NOTES:0:$BUDGET}"
|
|
NOTES=$(echo "$NOTES" | sed '$d')
|
|
NOTES="${NOTES}${TRAILER}"
|
|
fi
|
|
|
|
echo "$NOTES" > "$OUT_FILE"
|
|
echo "Wrote $OUT_FILE ($(wc -c < "$OUT_FILE") bytes)"
|
|
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
git add "$OUT_DIR/"
|
|
if git diff --cached --quiet; then
|
|
echo "No changelog changes."
|
|
else
|
|
git commit --amend --no-edit
|
|
git push --force-with-lease
|
|
fi
|
|
|
|
build-android:
|
|
needs: release-please
|
|
if: ${{ needs.release-please.outputs.release_created }}
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Java
|
|
uses: actions/setup-java@v4
|
|
with:
|
|
distribution: 'temurin'
|
|
java-version: '17'
|
|
cache: 'gradle'
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@v2
|
|
with:
|
|
channel: 'stable'
|
|
cache: true
|
|
|
|
- name: Cache pub dependencies
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.pub-cache
|
|
key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
|
|
restore-keys: pub-${{ runner.os }}-
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get
|
|
|
|
- name: Create .env
|
|
run: cp .env.example .env
|
|
|
|
- name: Decode keystore
|
|
run: echo ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | base64 -d > android/app/upload-keystore.jks
|
|
|
|
- name: Create key.properties
|
|
run: |
|
|
cat > android/key.properties <<EOF
|
|
storePassword=${{ secrets.ANDROID_STORE_PASSWORD }}
|
|
keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }}
|
|
keyAlias=${{ secrets.ANDROID_KEY_ALIAS }}
|
|
storeFile=upload-keystore.jks
|
|
EOF
|
|
|
|
- name: Build APK
|
|
run: flutter build apk --release --obfuscate --split-debug-info=build/debug-info-apk --dart-define-from-file=.env
|
|
|
|
- name: Build App Bundle
|
|
run: flutter build appbundle --release --obfuscate --split-debug-info=build/debug-info-aab --dart-define-from-file=.env
|
|
|
|
- name: Rename artifacts
|
|
run: |
|
|
mv build/app/outputs/flutter-apk/app-release.apk build/app/outputs/flutter-apk/pantry-${{ needs.release-please.outputs.version }}.apk
|
|
mv build/app/outputs/bundle/release/app-release.aab build/app/outputs/bundle/release/pantry-${{ needs.release-please.outputs.version }}.aab
|
|
|
|
- name: Upload APK to release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: ${{ needs.release-please.outputs.tag_name }}
|
|
files: |
|
|
build/app/outputs/flutter-apk/pantry-${{ needs.release-please.outputs.version }}.apk
|
|
|
|
- name: Upload App Bundle to release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: ${{ needs.release-please.outputs.tag_name }}
|
|
files: |
|
|
build/app/outputs/bundle/release/pantry-${{ needs.release-please.outputs.version }}.aab
|
|
|
|
build-ios:
|
|
needs: release-please
|
|
if: false # TEMPORARILY DISABLED — was: ${{ needs.release-please.outputs.release_created }}
|
|
runs-on: macos-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@v2
|
|
with:
|
|
channel: 'stable'
|
|
cache: true
|
|
|
|
- name: Cache pub dependencies
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.pub-cache
|
|
key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
|
|
restore-keys: pub-${{ runner.os }}-
|
|
|
|
- name: Cache CocoaPods
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
ios/Pods
|
|
~/.cocoapods
|
|
key: pods-${{ runner.os }}-${{ hashFiles('ios/Podfile') }}
|
|
restore-keys: pods-${{ runner.os }}-
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get
|
|
|
|
- name: Create .env
|
|
run: cp .env.example .env
|
|
|
|
- name: Build iOS (no codesign)
|
|
run: flutter build ios --release --no-codesign --obfuscate --split-debug-info=build/debug-info-ios --dart-define-from-file=.env
|
|
|
|
- name: Create unsigned IPA
|
|
run: |
|
|
mkdir -p build/ios/ipa
|
|
cd build/ios/iphoneos
|
|
mkdir -p Payload
|
|
cp -r Runner.app Payload/
|
|
zip -r ../ipa/pantry-${{ needs.release-please.outputs.version }}-unsigned.ipa Payload
|
|
|
|
- name: Upload IPA to release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: ${{ needs.release-please.outputs.tag_name }}
|
|
files: |
|
|
build/ios/ipa/pantry-${{ needs.release-please.outputs.version }}-unsigned.ipa
|
|
|
|
post-release-comment:
|
|
needs: [release-please, build-android]
|
|
if: ${{ needs.release-please.outputs.release_created }}
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Comment on release PR with asset links
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
TAG="${{ needs.release-please.outputs.tag_name }}"
|
|
VERSION="${{ needs.release-please.outputs.version }}"
|
|
REPO="${{ github.repository }}"
|
|
|
|
ASSETS=$(gh release view "$TAG" --repo "$REPO" --json assets --jq '.assets[].name')
|
|
|
|
ROWS=""
|
|
for ASSET in $ASSETS; do
|
|
URL="https://github.com/${REPO}/releases/download/${TAG}/${ASSET}"
|
|
ROWS="${ROWS}| ${ASSET} | [Download](${URL}) |
|
|
"
|
|
done
|
|
|
|
BODY="## Release Assets — ${TAG}
|
|
|
|
| File | Link |
|
|
|------|------|
|
|
${ROWS}"
|
|
|
|
PR_NUMBER=$(gh pr list --state merged --json number,title --repo "$REPO" \
|
|
--jq "[.[] | select(.title == \"chore(master): release ${VERSION}\")] | .[0].number")
|
|
|
|
if [ -z "$PR_NUMBER" ] || [ "$PR_NUMBER" = "null" ]; then
|
|
echo "No release PR found, skipping comment"
|
|
exit 0
|
|
fi
|
|
|
|
echo "Found release PR #${PR_NUMBER}"
|
|
gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$BODY"
|