From 83c05ad99ee6c9ecf327982a59937418381f40d9 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Thu, 5 Mar 2026 15:30:27 -0500 Subject: [PATCH] Improve release scripts and make workflows manual Redirect script informational/warning output to stderr and improve robustness of release tooling. Changes include: - Redirect many echo messages to stderr so scripts can emit machine-readable output on stdout. - Extract-release-notes: better parsing of CHANGELOG entries (tries v-prefixed and non-prefixed headings, cleaner note formatting) and improved fallbacks when changelog is missing. - Extract-version: accept versions with +build or -suffix, add diagnostic output when pubspec is missing, and tighten validation. - Setup/verify APK signing: more consistent stderr logging and clearer warnings; ensure keystore decoding/logging is visible. - Minor script usage message fixes (generate-tag-name, attach-apk-to-release). - CI/workflows: change backend-foundation, mobile-ci, and web-quality triggers to workflow_dispatch (manual runs); update product-release (make scripts step label emoji, remove node cache lines, bump Flutter to 3.38.x). These changes improve CI reliability, make scripts friendlier for automated consumers, and fix release note/version parsing edge cases. --- .github/scripts/attach-apk-to-release.sh | 12 +++--- .github/scripts/extract-release-notes.sh | 52 +++++++++++++----------- .github/scripts/extract-version.sh | 26 +++++++----- .github/scripts/generate-tag-name.sh | 4 +- .github/scripts/setup-apk-signing.sh | 22 +++++----- .github/scripts/verify-apk-signature.sh | 34 ++++++++-------- .github/workflows/backend-foundation.yml | 9 +--- .github/workflows/mobile-ci.yml | 11 +---- .github/workflows/product-release.yml | 6 +-- .github/workflows/web-quality.yml | 9 +--- 10 files changed, 85 insertions(+), 100 deletions(-) diff --git a/.github/scripts/attach-apk-to-release.sh b/.github/scripts/attach-apk-to-release.sh index 174023aa..4491178f 100755 --- a/.github/scripts/attach-apk-to-release.sh +++ b/.github/scripts/attach-apk-to-release.sh @@ -28,8 +28,8 @@ VERSION="$4" ENV="$5" if [ -z "$TAG_NAME" ] || [ -z "$APP" ] || [ -z "$APP_NAME" ] || [ -z "$VERSION" ] || [ -z "$ENV" ]; then - echo "❌ Error: Missing required arguments" - echo "Usage: $0 " + echo "❌ Error: Missing required arguments" >&2 + echo "Usage: $0 " >&2 exit 1 fi @@ -37,8 +37,8 @@ fi APK_PATH="apps/mobile/apps/${APP_NAME}/build/app/outputs/flutter-apk/app-release.apk" if [ ! -f "$APK_PATH" ]; then - echo "❌ Error: APK not found at $APK_PATH" - echo "Searching for APK files..." + echo "❌ Error: APK not found at $APK_PATH" >&2 + echo "Searching for APK files..." >&2 find apps/mobile/apps/${APP_NAME} -name "*.apk" exit 1 fi @@ -54,7 +54,7 @@ fi cp "$APK_PATH" "/tmp/$APK_NAME" # Upload to GitHub Release -echo "📤 Uploading $APK_NAME to release $TAG_NAME..." +echo "📤 Uploading $APK_NAME to release $TAG_NAME..." >&2 gh release upload "$TAG_NAME" "/tmp/$APK_NAME" --clobber -echo "✅ APK attached to release: $APK_NAME" +echo "✅ APK attached to release: $APK_NAME" >&2 diff --git a/.github/scripts/extract-release-notes.sh b/.github/scripts/extract-release-notes.sh index f29530fe..408d969f 100755 --- a/.github/scripts/extract-release-notes.sh +++ b/.github/scripts/extract-release-notes.sh @@ -11,8 +11,8 @@ TAG_NAME=$4 OUTPUT_FILE=$5 if [ -z "$APP" ] || [ -z "$VERSION" ] || [ -z "$ENV" ] || [ -z "$TAG_NAME" ] || [ -z "$OUTPUT_FILE" ]; then - echo "❌ Error: Missing required parameters" - echo "Usage: ./extract-release-notes.sh " + echo "❌ Error: Missing required parameters" >&2 + echo "Usage: ./extract-release-notes.sh " >&2 exit 1 fi @@ -27,39 +27,45 @@ fi # Try to extract release notes for this version if [ -f "$CHANGELOG_PATH" ]; then - echo "📝 Found CHANGELOG at $CHANGELOG_PATH" + echo "📝 Found CHANGELOG at $CHANGELOG_PATH" >&2 # Extract section for this version - # Look for ## [VERSION] and collect until next ## [ or end of file - NOTES=$(awk "/## \[${VERSION}\]/,/^## \[/" "$CHANGELOG_PATH" | sed '1d;$d' | sed '/^$/d') + # Look for ## [vVERSION] or ## [VERSION] and collect content until next ## [ header + # Try with 'v' prefix first (common format), then without + CHANGELOG_CONTENT=$(awk "/^## \[v${VERSION}\]/{flag=1; next} /^## \[/{flag=0} flag" "$CHANGELOG_PATH") - if [ -z "$NOTES" ]; then - echo "⚠️ Warning: No CHANGELOG entry found for version $VERSION" - NOTES="Release $VERSION for $APP_NAME + # If still empty, try without 'v' prefix + if [ -z "$CHANGELOG_CONTENT" ]; then + CHANGELOG_CONTENT=$(awk "/^## \[${VERSION}\]/{flag=1; next} /^## \[/{flag=0} flag" "$CHANGELOG_PATH") + fi + + if [ -z "$CHANGELOG_CONTENT" ]; then + echo "⚠️ Warning: No CHANGELOG entry found for version $VERSION" >&2 + NOTES="**Environment:** $ENV +**Tag:** $TAG_NAME -⚠️ No CHANGELOG entry found for this version. Please update the CHANGELOG manually. +## What is new in this release -**Environment:** $ENV -**Tag:** $TAG_NAME" +⚠️ No CHANGELOG entry found for this version. Please update the CHANGELOG manually." else - echo "✅ Extracted release notes for version $VERSION" - NOTES="# $APP_NAME - Release $VERSION + echo "✅ Extracted release notes for version $VERSION" >&2 + NOTES="**Environment:** $ENV +**Tag:** $TAG_NAME -$NOTES +## What is new in this release ---- - -**Environment:** $ENV -**Tag:** $TAG_NAME" +$CHANGELOG_CONTENT" fi else - echo "⚠️ Warning: CHANGELOG not found at $CHANGELOG_PATH" - NOTES="Release $VERSION for $APP_NAME + echo "⚠️ Warning: CHANGELOG not found at $CHANGELOG_PATH" >&2 + NOTES="**Environment:** $ENV +**Tag:** $TAG_NAME -**Environment:** $ENV -**Tag:** $TAG_NAME" +## What is new in this release + +⚠️ CHANGELOG file not found at $CHANGELOG_PATH" fi # Save to output file echo "$NOTES" > "$OUTPUT_FILE" -echo "✅ Release notes saved to $OUTPUT_FILE" +echo "✅ Release notes saved to $OUTPUT_FILE" >&2 diff --git a/.github/scripts/extract-version.sh b/.github/scripts/extract-version.sh index 88d97dd8..51e5b031 100755 --- a/.github/scripts/extract-version.sh +++ b/.github/scripts/extract-version.sh @@ -8,7 +8,7 @@ set -e APP=$1 if [ -z "$APP" ]; then - echo "❌ Error: App parameter required (worker-mobile-app or client-mobile-app)" + echo "❌ Error: App parameter required (worker-mobile-app or client-mobile-app)" >&2 exit 1 fi @@ -23,26 +23,30 @@ fi # Check if pubspec exists if [ ! -f "$PUBSPEC_PATH" ]; then - echo "❌ Error: pubspec.yaml not found at $PUBSPEC_PATH" + echo "❌ Error: pubspec.yaml not found at $PUBSPEC_PATH" >&2 + echo "📁 Current directory: $(pwd)" >&2 + echo "📂 Directory contents:" >&2 + ls -la apps/mobile/apps/ 2>&1 | head -20 >&2 exit 1 fi -# Extract version (format: X.Y.Z+buildNumber) +# Extract version (format: X.Y.Z+buildNumber or X.Y.Z-suffix) VERSION_LINE=$(grep "^version:" "$PUBSPEC_PATH") if [ -z "$VERSION_LINE" ]; then - echo "❌ Error: Could not find version in $PUBSPEC_PATH" + echo "❌ Error: Could not find version in $PUBSPEC_PATH" >&2 exit 1 fi -# Extract just the semantic version (before the +) -VERSION=$(echo "$VERSION_LINE" | sed 's/version: *//' | sed 's/+.*//' | tr -d ' ') +# Extract full version including suffix/build number +VERSION=$(echo "$VERSION_LINE" | sed 's/version: *//' | tr -d ' ') -# Validate version format -if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "❌ Error: Invalid version format in pubspec.yaml: $VERSION" - echo "Expected format: X.Y.Z (e.g., 0.1.0)" +# Validate version format (X.Y.Z with optional +build or -suffix) +# Use grep for better portability across different bash versions +if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(\+[a-zA-Z0-9]+|-[a-zA-Z0-9]+)?$'; then + echo "❌ Error: Invalid version format in pubspec.yaml: $VERSION" >&2 + echo "Expected format: X.Y.Z, X.Y.Z+build, or X.Y.Z-suffix (e.g., 0.1.0, 0.1.0+12, 0.1.0-m3)" >&2 exit 1 fi -echo "✅ Extracted version from $PUBSPEC_PATH: $VERSION" +echo "✅ Extracted version from $PUBSPEC_PATH: $VERSION" >&2 echo "$VERSION" diff --git a/.github/scripts/generate-tag-name.sh b/.github/scripts/generate-tag-name.sh index c779b542..8376a217 100755 --- a/.github/scripts/generate-tag-name.sh +++ b/.github/scripts/generate-tag-name.sh @@ -9,8 +9,8 @@ ENV=$2 VERSION=$3 if [ -z "$APP" ] || [ -z "$ENV" ] || [ -z "$VERSION" ]; then - echo "❌ Error: Missing required parameters" - echo "Usage: ./generate-tag-name.sh " + echo "❌ Error: Missing required parameters" >&2 + echo "Usage: ./generate-tag-name.sh " >&2 exit 1 fi diff --git a/.github/scripts/setup-apk-signing.sh b/.github/scripts/setup-apk-signing.sh index fe982f6a..197df4eb 100755 --- a/.github/scripts/setup-apk-signing.sh +++ b/.github/scripts/setup-apk-signing.sh @@ -32,12 +32,12 @@ ENV="$2" TEMP_DIR="$3" if [ -z "$APP" ] || [ -z "$ENV" ] || [ -z "$TEMP_DIR" ]; then - echo "❌ Error: Missing required arguments" - echo "Usage: $0 " + echo "❌ Error: Missing required arguments" >&2 + echo "Usage: $0 " >&2 exit 1 fi -echo "🔐 Setting up Android signing for $APP in $ENV environment..." +echo "🔐 Setting up Android signing for $APP in $ENV environment..." >&2 # Determine which keystore to use if [ "$APP" = "worker-mobile-app" ]; then @@ -68,9 +68,9 @@ KEY_PASSWORD="${!KEY_PASSWORD_VAR}" # Check if secrets are configured if [ -z "$KEYSTORE_BASE64" ]; then - echo "⚠️ WARNING: Keystore secret $KEYSTORE_BASE64_VAR is not configured!" - echo "⚠️ APK will be built UNSIGNED for $ENV environment." - echo "⚠️ Please configure GitHub Secrets as documented in docs/RELEASE/APK_SIGNING_SETUP.md" + echo "⚠️ WARNING: Keystore secret $KEYSTORE_BASE64_VAR is not configured!" >&2 + echo "⚠️ APK will be built UNSIGNED for $ENV environment." >&2 + echo "⚠️ Please configure GitHub Secrets as documented in docs/RELEASE/APK_SIGNING_SETUP.md" >&2 exit 0 fi @@ -83,12 +83,12 @@ KEYSTORE_PATH="$KEYSTORE_DIR/release.jks" echo "$KEYSTORE_BASE64" | base64 -d > "$KEYSTORE_PATH" if [ ! -f "$KEYSTORE_PATH" ]; then - echo "❌ Failed to decode keystore!" + echo "❌ Failed to decode keystore!" >&2 exit 1 fi -echo "✅ Keystore decoded successfully" -echo "📦 Keystore size: $(ls -lh "$KEYSTORE_PATH" | awk '{print $5}')" +echo "✅ Keystore decoded successfully" >&2 +echo "📦 Keystore size: $(ls -lh "$KEYSTORE_PATH" | awk '{print $5}')" >&2 # Export environment variables for build.gradle.kts # Using CodeMagic-compatible variable names @@ -98,5 +98,5 @@ echo "CM_KEYSTORE_PASSWORD_${APP_NAME}=$KEYSTORE_PASSWORD" >> $GITHUB_ENV echo "CM_KEY_ALIAS_${APP_NAME}=$KEY_ALIAS" >> $GITHUB_ENV echo "CM_KEY_PASSWORD_${APP_NAME}=$KEY_PASSWORD" >> $GITHUB_ENV -echo "✅ Signing environment configured for $APP_NAME ($ENV environment)" -echo "🔑 Using key alias: $KEY_ALIAS" +echo "✅ Signing environment configured for $APP_NAME ($ENV environment)" >&2 +echo "🔑 Using key alias: $KEY_ALIAS" >&2 diff --git a/.github/scripts/verify-apk-signature.sh b/.github/scripts/verify-apk-signature.sh index 16832d02..eec7088a 100755 --- a/.github/scripts/verify-apk-signature.sh +++ b/.github/scripts/verify-apk-signature.sh @@ -18,41 +18,41 @@ set -e APK_PATH="$1" if [ -z "$APK_PATH" ]; then - echo "❌ Error: Missing APK path" - echo "Usage: $0 " + echo "❌ Error: Missing APK path" >&2 + echo "Usage: $0 " >&2 exit 1 fi if [ ! -f "$APK_PATH" ]; then - echo "❌ APK not found at: $APK_PATH" + echo "❌ APK not found at: $APK_PATH" >&2 exit 1 fi -echo "🔍 Verifying APK signature..." +echo "🔍 Verifying APK signature..." >&2 # Check if APK is signed if jarsigner -verify -verbose "$APK_PATH" 2>&1 | grep -q "jar verified"; then - echo "✅ APK is properly signed!" + echo "✅ APK is properly signed!" >&2 # Extract certificate details - echo "" - echo "📜 Certificate Details:" + echo "" >&2 + echo "📜 Certificate Details:" >&2 jarsigner -verify -verbose -certs "$APK_PATH" 2>&1 | grep -A 3 "X.509" || true # Get signer info - echo "" - echo "🔑 Signer Information:" + echo "" >&2 + echo "🔑 Signer Information:" >&2 keytool -printcert -jarfile "$APK_PATH" | head -n 15 else - echo "⚠️ WARNING: APK signature verification failed or APK is unsigned!" - echo "" - echo "This may happen if:" - echo " 1. GitHub Secrets are not configured for this environment" - echo " 2. Keystore credentials are incorrect" - echo " 3. Build configuration didn't apply signing" - echo "" - echo "See: docs/RELEASE/APK_SIGNING_SETUP.md for setup instructions" + echo "⚠️ WARNING: APK signature verification failed or APK is unsigned!" >&2 + echo "" >&2 + echo "This may happen if:" >&2 + echo " 1. GitHub Secrets are not configured for this environment" >&2 + echo " 2. Keystore credentials are incorrect" >&2 + echo " 3. Build configuration didn't apply signing" >&2 + echo "" >&2 + echo "See: docs/RELEASE/APK_SIGNING_SETUP.md for setup instructions" >&2 # Don't fail the build, just warn # exit 1 diff --git a/.github/workflows/backend-foundation.yml b/.github/workflows/backend-foundation.yml index 0e408f8f..a4a7d777 100644 --- a/.github/workflows/backend-foundation.yml +++ b/.github/workflows/backend-foundation.yml @@ -1,14 +1,7 @@ name: Backend Foundation on: - pull_request: - branches: - - dev - - main - push: - branches: - - dev - - main + workflow_dispatch: jobs: backend-foundation-makefile: diff --git a/.github/workflows/mobile-ci.yml b/.github/workflows/mobile-ci.yml index 1a439740..910576de 100644 --- a/.github/workflows/mobile-ci.yml +++ b/.github/workflows/mobile-ci.yml @@ -1,16 +1,7 @@ name: Mobile CI on: - pull_request: - paths: - - 'apps/mobile/**' - - '.github/workflows/mobile-ci.yml' - push: - branches: - - main - paths: - - 'apps/mobile/**' - - '.github/workflows/mobile-ci.yml' + workflow_dispatch: jobs: detect-changes: diff --git a/.github/workflows/product-release.yml b/.github/workflows/product-release.yml index f3f3930c..7e72e4ec 100644 --- a/.github/workflows/product-release.yml +++ b/.github/workflows/product-release.yml @@ -45,7 +45,7 @@ jobs: with: fetch-depth: 0 - - name: � Make scripts executable + - name: 🏃🏾‍♂️ Make scripts executable run: | chmod +x .github/scripts/*.sh echo "✅ Scripts are now executable" @@ -165,8 +165,6 @@ jobs: uses: actions/setup-node@v4 with: node-version: '20' - cache: 'npm' - cache-dependency-path: 'backend/*/package-lock.json' - name: 🔥 Install Firebase CLI run: | @@ -184,7 +182,7 @@ jobs: - name: 🐦 Setup Flutter uses: subosito/flutter-action@v2 with: - flutter-version: '3.24.5' + flutter-version: '3.38.x' channel: 'stable' cache: true diff --git a/.github/workflows/web-quality.yml b/.github/workflows/web-quality.yml index 7280b333..dd955c5c 100644 --- a/.github/workflows/web-quality.yml +++ b/.github/workflows/web-quality.yml @@ -1,14 +1,7 @@ name: Web Quality on: - pull_request: - branches: - - dev - - main - push: - branches: - - dev - - main + workflow_dispatch: jobs: web-quality: