Skip to content

fix(auth): Auto reroute to login on token expiration (#226) #65

fix(auth): Auto reroute to login on token expiration (#226)

fix(auth): Auto reroute to login on token expiration (#226) #65

Workflow file for this run

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 }}