fix(auth): Auto reroute to login on token expiration (#226) #65
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Flutter Build and Release on Main Branch Update | |
| on: | |
| push: | |
| branches: [ main ] | |
| jobs: | |
| build_and_release_on_main: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: read | |
| steps: | |
| # Checks out the repository code with full history for release purposes. | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| # Sets up the Flutter environment with a specific version and channel. | |
| - name: Set up Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: '3.38.4' | |
| channel: 'stable' | |
| # Installs all project dependencies listed in pubspec.yaml. | |
| - name: Install dependencies | |
| run: flutter pub get | |
| # Extracts the semantic version from the pubspec.yaml file. | |
| - name: Extract version from pubspec.yaml | |
| id: pubspec | |
| run: | | |
| VERSION_LINE=$(grep '^version:' pubspec.yaml) | |
| # Extract semantic version (e.g., 2.0.0) | |
| SEMANTIC_VERSION=$(echo "$VERSION_LINE" | sed -E 's/version: ([0-9]+\.[0-9]+\.[0-9]+)(\+.*)?/\1/' | tr -d '[:space:]') | |
| # Always use GitHub run number as the full build number | |
| FULL_BUILD_NUMBER="${{ github.run_number }}" | |
| FULL_VERSION="${SEMANTIC_VERSION}+${FULL_BUILD_NUMBER}" | |
| echo "semantic_version=$SEMANTIC_VERSION" >> $GITHUB_OUTPUT | |
| echo "full_build_number=$FULL_BUILD_NUMBER" >> $GITHUB_OUTPUT | |
| echo "full_version=$FULL_VERSION" >> $GITHUB_OUTPUT | |
| # Creates an .env file with the API base URL for the release build. | |
| - name: Create .env file for Release Build | |
| run: | | |
| echo "API_BASE_URL=${{ secrets.API_BASE_URL }}" > .env | |
| echo "API_BASE_URL_DEBUG=${{ secrets.API_BASE_URL_DEBUG }}" >> .env | |
| env: | |
| API_BASE_URL: ${{ secrets.API_BASE_URL }} | |
| API_BASE_URL_DEBUG: ${{ secrets.API_BASE_URL_DEBUG }} | |
| # Decode Keystore and Create Properties | |
| - name: Decode Keystore and Create Properties | |
| run: | | |
| echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > android/app/key.jks | |
| echo "storePassword=${{ secrets.STORE_PASSWORD }}" > android/key.properties | |
| echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/key.properties | |
| echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> android/key.properties | |
| echo "storeFile=app/key.jks" >> android/key.properties | |
| # Accepts Android SDK licenses. | |
| - name: Accept Android SDK licenses | |
| run: | | |
| export ANDROID_SDK_ROOT=/usr/local/lib/android/sdk | |
| yes | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --licenses | |
| # Create google-services.json from secret | |
| - name: Create google-services.json | |
| run: echo "${{ secrets.GOOGLE_SERVICES_JSON_BASE64 }}" | base64 --decode > android/app/google-services.json | |
| env: | |
| GOOGLE_SERVICES_JSON_BASE64: ${{ secrets.GOOGLE_SERVICES_JSON_BASE64 }} | |
| # Builds ABI-Specific Release APKs | |
| - name: Build ABI-Specific Release APKs | |
| run: flutter build apk --split-per-abi --release --build-name=${{ steps.pubspec.outputs.semantic_version }} --build-number=${{ steps.pubspec.outputs.full_build_number }} | |
| # Builds a universal (fat) Release APK. | |
| - name: Build Universal (Fat) Release APK | |
| run: flutter build apk --release --build-name=${{ steps.pubspec.outputs.semantic_version }} --build-number=${{ steps.pubspec.outputs.full_build_number }} | |
| # Creates an .env file with the API base URL for the debug build. | |
| - name: Create .env file for Debug Build | |
| run: echo "API_BASE_URL_DEBUG=${{ secrets.API_BASE_URL_DEBUG }}" > .env | |
| env: | |
| API_BASE_URL_DEBUG: ${{ secrets.API_BASE_URL_DEBUG }} | |
| # Builds a debug APK. | |
| - name: Build Debug APK | |
| run: flutter build apk --debug --build-name=${{ steps.pubspec.outputs.semantic_version }} --build-number=${{ steps.pubspec.outputs.full_build_number }} | |
| # Renames the universal release APK to include version and build number. | |
| - name: Rename Universal Release APK | |
| id: universal_release_apk_details | |
| run: | | |
| original_path="build/app/outputs/flutter-apk/app-release.apk" | |
| new_name="palapa_inspeksi-v${{ steps.pubspec.outputs.semantic_version }}-universal-release.apk" | |
| new_path="build/app/outputs/flutter-apk/$new_name" | |
| mv "$original_path" "$new_path" | |
| echo "path=$new_path" >> $GITHUB_OUTPUT | |
| echo "name=$new_name" >> $GITHUB_OUTPUT | |
| # Renames the arm64-v8a release APK to include version and build number. | |
| - name: Rename arm64-v8a Release APK | |
| id: arm64_v8a_release_apk_details | |
| run: | | |
| original_path="build/app/outputs/flutter-apk/app-arm64-v8a-release.apk" | |
| new_name="palapa_inspeksi-v${{ steps.pubspec.outputs.semantic_version }}-arm64-v8a-release.apk" | |
| new_path="build/app/outputs/flutter-apk/$new_name" | |
| mv "$original_path" "$new_path" | |
| echo "path=$new_path" >> $GITHUB_OUTPUT | |
| echo "name=$new_name" >> $GITHUB_OUTPUT | |
| # Renames the armeabi-v7a release APK to include version and build number. | |
| - name: Rename armeabi-v7a Release APK | |
| id: armeabi_v7a_release_apk_details | |
| run: | | |
| original_path="build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk" | |
| new_name="palapa_inspeksi-v${{ steps.pubspec.outputs.semantic_version }}-armeabi-v7a-release.apk" | |
| new_path="build/app/outputs/flutter-apk/$new_name" | |
| mv "$original_path" "$new_path" | |
| echo "path=$new_path" >> $GITHUB_OUTPUT | |
| echo "name=$new_name" >> $GITHUB_OUTPUT | |
| # Renames the debug APK to include version and build number. | |
| - name: Rename Debug APK | |
| id: debug_apk_details | |
| run: | | |
| original_path="build/app/outputs/flutter-apk/app-debug.apk" | |
| new_name="palapa_inspeksi-v${{ steps.pubspec.outputs.full_version }}-debug.apk" | |
| new_path="build/app/outputs/flutter-apk/$new_name" | |
| mv "$original_path" "$new_path" | |
| echo "path=$new_path" >> $GITHUB_OUTPUT | |
| echo "name=$new_name" >> $GITHUB_OUTPUT | |
| # Creates a release tag name based on the semantic version and run number. | |
| - name: Create Release Tag Name | |
| id: create_tag | |
| run: | | |
| TAG_NAME="v${{ steps.pubspec.outputs.semantic_version }}" | |
| echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| # Prepares the release body content, including PR details and commit information. | |
| - name: Prepare Release Body | |
| id: prep_release_body | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| // Your excellent release body script remains unchanged | |
| const { | |
| COMMIT_SHA, ACTOR, SEMANTIC_VERSION, RUN_NUMBER, REPO_URL, HEAD_COMMIT_MESSAGE, FULL_VERSION | |
| } = process.env; | |
| let main_release_content = ""; | |
| let pr_details_for_footer = ""; | |
| const pr_regex_merge = /Merge pull request #(\d+)/; | |
| const pr_regex_squash_title = /\(#(\d+)\)(?:$|\n)/; | |
| let match = HEAD_COMMIT_MESSAGE.match(pr_regex_merge); | |
| if (!match) { | |
| const first_line_of_commit = HEAD_COMMIT_MESSAGE.split('\n')[0]; | |
| match = first_line_of_commit.match(pr_regex_squash_title); | |
| } | |
| if (match && match[1]) { | |
| const pr_number = match[1]; | |
| core.info(`Attempting to fetch details for PR #${pr_number}`); | |
| try { | |
| const { data: pr } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: pr_number, | |
| }); | |
| main_release_content = pr.body || "No description provided for this Pull Request."; | |
| pr_details_for_footer += `**Pull Request:** [#${pr_number}: ${pr.title}](${pr.html_url})\n`; | |
| pr_details_for_footer += `**PR Author:** @${pr.user.login}\n`; | |
| } catch (error) { | |
| core.warning(`Could not fetch details for PR #${pr_number}: ${error.message}`); | |
| main_release_content = `Could not automatically fetch Pull Request description for PR #${pr_number}. Please refer to the PR or commit message directly.\n\n`; | |
| main_release_content += `Associated PR: [#${pr_number}](${REPO_URL}/pull/${pr_number})\n`; | |
| } | |
| } else { | |
| core.info("Could not determine PR from commit message. Using commit message as main content."); | |
| const commit_title = HEAD_COMMIT_MESSAGE.split('\n')[0]; | |
| let commit_body_part = HEAD_COMMIT_MESSAGE.substring(commit_title.length).trim(); | |
| if (commit_body_part) { | |
| main_release_content = `**${commit_title}**\n\n${commit_body_part}`; | |
| } else { | |
| main_release_content = HEAD_COMMIT_MESSAGE; | |
| } | |
| } | |
| let footer_info = "\n\n---\n\n"; | |
| footer_info += `**Version:** v${SEMANTIC_VERSION}\n`; | |
| footer_info += `**Released by:** @${ACTOR}\n`; | |
| footer_info += pr_details_for_footer; | |
| footer_info += `**Commit:** [${COMMIT_SHA.substring(0,7)}](${REPO_URL}/commit/${COMMIT_SHA})\n`; | |
| footer_info += `\n**Full Commit Message:**\n\`\`\`\n${HEAD_COMMIT_MESSAGE}\n\`\`\`\n`; | |
| const release_body = main_release_content + footer_info; | |
| core.setOutput("body", release_body); | |
| env: | |
| SEMANTIC_VERSION: ${{ steps.pubspec.outputs.semantic_version }} | |
| RUN_NUMBER: ${{ github.run_number }} | |
| COMMIT_SHA: ${{ github.sha }} | |
| ACTOR: ${{ github.actor }} | |
| REPO_URL: ${{ github.server_url }}/${{ github.repository }} | |
| HEAD_COMMIT_MESSAGE: ${{ github.event.head_commit.message }} | |
| FULL_VERSION: ${{ steps.pubspec.outputs.full_version }} | |
| # Creates a new GitHub Release. | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: ${{ steps.create_tag.outputs.tag_name }} | |
| name: "v${{ steps.pubspec.outputs.semantic_version }}" | |
| body: ${{ steps.prep_release_body.outputs.body }} | |
| draft: false | |
| prerelease: false | |
| files: | | |
| ${{ steps.universal_release_apk_details.outputs.path }} | |
| ${{ steps.arm64_v8a_release_apk_details.outputs.path }} | |
| ${{ steps.armeabi_v7a_release_apk_details.outputs.path }} | |
| ${{ steps.debug_apk_details.outputs.path }} | |
| # Uploads all release APKs as a build artifact. | |
| - name: Upload All Release APKs as Build Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-apks-v${{ steps.pubspec.outputs.semantic_version }} | |
| path: | | |
| ${{ steps.universal_release_apk_details.outputs.path }} | |
| ${{ steps.arm64_v8a_release_apk_details.outputs.path }} | |
| ${{ steps.armeabi_v7a_release_apk_details.outputs.path }} | |
| if-no-files-found: warn | |
| # Uploads the debug build artifact. | |
| - name: Upload Debug Build Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: debug-apk-v${{ steps.pubspec.outputs.semantic_version }} | |
| path: ${{ steps.debug_apk_details.outputs.path }} |