Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions build/Android-Ios-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: 🏷️ Semantic Release & 📱 Mobile Build (Android + iOS)

on:
push:
branches:
- main
Comment on lines +3 to +6
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Workflow only triggers on main branch push.

The workflow is set to run only on push to main. This means releases will be published immediately on every commit to main, which may be unintended. Consider triggering only on tags or adding a manual dispatch option if more control is desired.

Consider using tags or manual dispatch for release workflows:

 on:
   push:
     branches:
       - main
+    tags:
+      - 'v*'
+  workflow_dispatch:

Or, restrict to main and add a tag requirement:

 on:
   push:
     branches:
       - main
     tags:
       - 'v*'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
push:
branches:
- main
on:
push:
branches:
- main
tags:
- 'v*'
workflow_dispatch:
🤖 Prompt for AI Agents
In build/Android-Ios-deploy.yml around lines 3 to 6, the workflow is currently
triggered on every push to main which will publish releases on each commit;
change the on: configuration to trigger only on tag creation (e.g. push with
tags: ['v*.*.*']) or add workflow_dispatch for manual runs (or both) so releases
are controlled; update the YAML to replace or augment the push:branches: - main
block with a push:tags pattern and/or include workflow_dispatch and document the
expected tag format in the workflow comments.


permissions:
contents: write
packages: write
issues: write
pull-requests: write

jobs:
release:
name: 🚀 Semantic Release & Android Build
runs-on: ubuntu-latest

steps:
# 🧩 Checkout the repository
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0

# ⚙️ Setup Node.js for semantic-release
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"

# 🧰 Install release tools
- name: Install release tools
run: |
npm install -g semantic-release \
@semantic-release/changelog \
@semantic-release/git \
@semantic-release/commit-analyzer \
@semantic-release/release-notes-generator \
@semantic-release/github

# 🏷️ Get next version (dry-run)
- name: Get next release version
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(npx semantic-release --dry-run | grep "The next release version is" | awk '{print $NF}')
echo "version=${VERSION:-0.0.0}" >> $GITHUB_OUTPUT
Comment on lines +43 to +49
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing job output declaration—iOS job will fail to access version.

The release job sets steps.semantic.outputs.version at line 49, but this is only a step output. The iOS job (line 148) references needs.release.outputs.version, which requires the job to explicitly declare outputs. Without this, the iOS step will receive an empty or undefined version.

Apply this diff to declare the version output from the release job:

      - name: Get next release version
        id: semantic
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          VERSION=$(npx semantic-release --dry-run | grep "The next release version is" | awk '{print $NF}')
          echo "version=${VERSION:-0.0.0}" >> $GITHUB_OUTPUT

+   outputs:
+     version: ${{ steps.semantic.outputs.version }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Get next release version
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(npx semantic-release --dry-run | grep "The next release version is" | awk '{print $NF}')
echo "version=${VERSION:-0.0.0}" >> $GITHUB_OUTPUT
- name: Get next release version
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(npx semantic-release --dry-run | grep "The next release version is" | awk '{print $NF}')
echo "version=${VERSION:-0.0.0}" >> $GITHUB_OUTPUT
outputs:
version: ${{ steps.semantic.outputs.version }}
🤖 Prompt for AI Agents
In build/Android-Ios-deploy.yml around lines 43 to 49, the release job only sets
a step output (steps.semantic.outputs.version) but does not declare a job-level
output, so downstream jobs using needs.release.outputs.version will be empty;
declare a job output by adding an outputs block on the release job mapping
version to the step output (e.g., outputs: version: ${{
steps.semantic.outputs.version }}), ensuring the semantic step keeps the id
"semantic" and its version is exported to GITHUB_OUTPUT as before.


# 🧱 Setup Java (for Android)
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17

# 🧩 Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

# 🏗️ Build APK (Release)
- name: Build APK
run: ./gradlew assembleRelease
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

No error handling for build failures; downstream steps will execute regardless.

If the APK build (line 64) or pod install (line 114) fails, subsequent steps (signing, archiving, etc.) will still run, potentially causing confusing errors or wasted resource cycles.

Consider adding explicit error checks or using GitHub Actions' native if: conditions to halt on failure:

       # 🏗️ Build APK (Release)
       - name: Build APK
         run: ./gradlew assembleRelease
+        if: success()

Similarly for the iOS CocoaPods installation:

       - name: Install CocoaPods
-        run: pod install --project-directory=ios
+        run: |
+          if [ ! -d "ios" ]; then
+            echo "Error: ios directory not found" >&2
+            exit 1
+          fi
+          pod install --project-directory=ios

Also applies to: 114-114


# 🔏 Sign APK
- name: Sign APK
uses: r0adkll/sign-android-release@v1
with:
releaseDirectory: app/build/outputs/apk/release
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}

# 🧩 Rename APK
- name: Rename APK with version
run: |
VERSION=${{ steps.semantic.outputs.version }}
mkdir -p dist
cp app/build/outputs/apk/release/app-release-signed.apk dist/app-release-v${VERSION}.apk
echo "APK_NAME=app-release-v${VERSION}.apk" >> $GITHUB_ENV

# 🏷️ Run semantic-release to publish release + attach APK
- name: Run semantic-release (publish)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx semantic-release --assets "dist/${APK_NAME}"

ios:
name: 🍎 iOS Build & Release
runs-on: macos-latest
needs: release

steps:
# 🧩 Checkout repo
- name: Checkout repo
uses: actions/checkout@v4

# ⚙️ Setup Node.js (for semantic-release)
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"

# 🍏 Setup Ruby & CocoaPods
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'

- name: Install CocoaPods
run: pod install --project-directory=ios

# 🔑 Setup Xcode environment
- name: Select Xcode version
run: sudo xcode-select -s /Applications/Xcode_15.4.app

# 🔏 Setup Signing Certificates & Provisioning Profile
- name: Setup signing
uses: apple-actions/import-codesign-certs@v2
with:
p12-file-base64: ${{ secrets.IOS_CERTIFICATES_P12 }}
p12-password: ${{ secrets.IOS_CERTIFICATES_PASSWORD }}
provisioning-profile-base64: ${{ secrets.IOS_PROVISION_PROFILE }}

# 🏗️ Build iOS app (Release)
- name: Build iOS app
run: |
xcodebuild -workspace ios/YourApp.xcworkspace \
-scheme YourApp \
-configuration Release \
-archivePath build/YourApp.xcarchive \
archive DEVELOPMENT_TEAM=${{ secrets.APPLE_TEAM_ID }} \
CODE_SIGN_STYLE=Manual \
CODE_SIGN_IDENTITY="Apple Distribution" \
PROVISIONING_PROFILE_SPECIFIER="${{ secrets.IOS_PROFILE_NAME }}"

xcodebuild -exportArchive \
-archivePath build/YourApp.xcarchive \
-exportPath dist \
-exportOptionsPlist ios/exportOptions.plist
Comment on lines +131 to +143
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Replace hardcoded template placeholders with environment variables or documentation.

The xcodebuild commands reference hardcoded values (ios/YourApp.xcworkspace, YourApp, build/YourApp.xcarchive, dist, ios/exportOptions.plist). These are template placeholders that must be replaced for each project. This is error-prone and not clearly documented.

Apply this diff to parameterize key values and add documentation:

+      # 🔧 Set build configuration variables
+      - name: Set iOS build variables
+        run: |
+          echo "IOS_WORKSPACE=ios/YourApp.xcworkspace" >> $GITHUB_ENV
+          echo "IOS_SCHEME=YourApp" >> $GITHUB_ENV
+          echo "IOS_ARCHIVE_PATH=build/YourApp.xcarchive" >> $GITHUB_ENV
+          echo "EXPORT_OPTIONS_PLIST=ios/exportOptions.plist" >> $GITHUB_ENV
+
       # 🏗️ Build iOS app (Release)
       - name: Build iOS app
         run: |
-          xcodebuild -workspace ios/YourApp.xcworkspace \
-            -scheme YourApp \
+          xcodebuild -workspace ${{ env.IOS_WORKSPACE }} \
+            -scheme ${{ env.IOS_SCHEME }} \
             -configuration Release \
-            -archivePath build/YourApp.xcarchive \
+            -archivePath ${{ env.IOS_ARCHIVE_PATH }} \
             archive DEVELOPMENT_TEAM=${{ secrets.APPLE_TEAM_ID }} \
             CODE_SIGN_STYLE=Manual \
             CODE_SIGN_IDENTITY="Apple Distribution" \
             PROVISIONING_PROFILE_SPECIFIER="${{ secrets.IOS_PROFILE_NAME }}"
 
           xcodebuild -exportArchive \
-            -archivePath build/YourApp.xcarchive \
+            -archivePath ${{ env.IOS_ARCHIVE_PATH }} \
             -exportPath dist \
-            -exportOptionsPlist ios/exportOptions.plist
+            -exportOptionsPlist ${{ env.EXPORT_OPTIONS_PLIST }}

Additionally, add a comment block at the top of the iOS job documenting required configuration values (workspace name, scheme, etc.).

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In build/Android-Ios-deploy.yml around lines 131 to 143, the xcodebuild calls
use hardcoded template placeholders (workspace, scheme, archive path, export
path, exportOptions.plist); replace those literals with CI variables (e.g. ${{
env.IOS_WORKSPACE }}, ${{ env.IOS_SCHEME }}, ${{ env.IOS_ARCHIVE_PATH }}, ${{
env.IOS_EXPORT_PATH }}, ${{ env.IOS_EXPORT_OPTIONS_PLIST }} or secrets where
appropriate) and reference them in the xcodebuild commands so the workflow is
reusable; add a comment block at the top of the iOS job listing required
configuration keys and example values (workspace name, scheme, archive path,
export path, exportOptions plist, DEVELOPMENT_TEAM and provisioning profile
secret names) and ensure the workflow supplies sensible defaults or fails with a
clear error if required env vars/secrets are missing.


# 🧩 Rename IPA
- name: Rename IPA with version
run: |
VERSION=${{ needs.release.outputs.version }}
mv dist/YourApp.ipa dist/YourApp-v${VERSION}.ipa
echo "IPA_NAME=YourApp-v${VERSION}.ipa" >> $GITHUB_ENV

# 📦 Upload IPA to release
- name: Upload IPA to GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload v${{ needs.release.outputs.version }} "dist/${IPA_NAME}" --clobber
89 changes: 89 additions & 0 deletions build/Android-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: 🏷️ Semantic Release & 📱 Android Build

on:
push:
branches:
- main

permissions:
contents: write
packages: write
issues: write
pull-requests: write

jobs:
release:
name: 🚀 Semantic Release & Build
runs-on: ubuntu-latest

steps:
# 🧩 Checkout the repository
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0

# ⚙️ Setup Node.js for release management
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"

# 🧰 Install semantic-release and plugins
- name: Install release tools
run: |
npm install -g semantic-release \
@semantic-release/changelog \
@semantic-release/git \
@semantic-release/commit-analyzer \
@semantic-release/release-notes-generator \
@semantic-release/github

# 🏷️ Run semantic-release to manage versions
- name: Run semantic-release (dry-run to get next version)
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(npx semantic-release --dry-run | grep "The next release version is" | awk '{print $NF}')
echo "version=$VERSION" >> $GITHUB_OUTPUT || echo "version=0.0.0" >> $GITHUB_OUTPUT
Comment on lines +43 to +49
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Major: Semantic-release executed twice with risk of version mismatch.

The workflow runs semantic-release twice: once as dry-run (line 43) to extract the version, and once to publish (line 85). This introduces:

  1. Version mismatch risk: Commits pushed between the two runs could cause semantic-release to compute a different version on the second run.
  2. Inefficiency: semantic-release should be run once; both the version and publish status should be captured in a single invocation.
  3. Complexity: The dry-run → extract version → use version → publish flow is harder to maintain.

Refactor to run semantic-release once and use its structured logging or the generated GITHUB_OUTPUT to determine if a release was generated:

-      - name: Run semantic-release (dry-run to get next version)
-        id: semantic
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        run: |
-          VERSION=$(npx semantic-release --dry-run | grep "The next release version is" | awk '{print $NF}')
-          echo "version=$VERSION" >> $GITHUB_OUTPUT || echo "version=0.0.0" >> $GITHUB_OUTPUT
       # ... [Java, Gradle, Build, Sign steps remain unchanged] ...
-      - name: Run semantic-release and upload APK
+      - name: Extract version and prepare APK
+        id: semantic
+        run: |
+          output=$(npx semantic-release --dry-run 2>&1)
+          VERSION=$(echo "$output" | grep "The next release version is" | awk '{print $NF}')
+          echo "version=$VERSION" >> $GITHUB_OUTPUT
+
+      - name: Run semantic-release and upload APK
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         run: |
           npx semantic-release --assets "dist/${APK_NAME}"

Also applies to: 85-89


⚠️ Potential issue | 🔴 Critical

Critical: Fragile semantic-release version parsing with silent failure fallback.

The version extraction logic using grep/awk is unreliable and masks failures:

  1. The grep pattern "The next release version is" is not guaranteed to match semantic-release --dry-run output across all versions.
  2. If the pattern doesn't match, $VERSION is empty, and the fallback || echo "version=0.0.0" silently masks the failure.
  3. There is no validation that version extraction succeeded before proceeding.
  4. If version extraction fails, the APK will be named app-release-v.apk or app-release-v0.0.0.apk (incorrect).

Consider using semantic-release's structured output or a more robust parsing approach. Alternatively, run semantic-release once and capture both the version and success status:

-      - name: Run semantic-release (dry-run to get next version)
-        id: semantic
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        run: |
-          VERSION=$(npx semantic-release --dry-run | grep "The next release version is" | awk '{print $NF}')
-          echo "version=$VERSION" >> $GITHUB_OUTPUT || echo "version=0.0.0" >> $GITHUB_OUTPUT
+      - name: Run semantic-release (dry-run to get next version)
+        id: semantic
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: |
+          output=$(npx semantic-release --dry-run 2>&1)
+          if echo "$output" | grep -q "The next release version is"; then
+            VERSION=$(echo "$output" | grep "The next release version is" | awk '{print $NF}')
+          else
+            echo "Error: Failed to extract version from semantic-release output"
+            echo "$output"
+            exit 1
+          fi
+          if [[ -z "$VERSION" ]]; then
+            echo "Error: Extracted version is empty"
+            exit 1
+          fi
+          echo "version=$VERSION" >> $GITHUB_OUTPUT
🤖 Prompt for AI Agents
In build/Android-deploy.yml around lines 43–49, the current grep/awk extraction
is brittle and silently falls back to version 0.0.0; instead run
semantic-release once and fail-fast if it doesn't produce a valid semver:
execute semantic-release and capture its output and exit code, parse the output
with a strict semver regex (e.g. /^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$/)
or, preferably, use semantic-release's structured/JSON output or API if
available, validate the parsed version is non-empty and matches semver, write
the validated version to GITHUB_OUTPUT, and exit the job with non-zero status if
extraction fails (do not silently write 0.0.0).


# 🧱 Setup Java (required for Android build)
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17

# 🧩 Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

# 🏗️ Build the APK (Release)
- name: Build APK
run: ./gradlew assembleRelease
Comment on lines +63 to +64
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Major: Build step lacks explicit error handling.

Line 64 runs ./gradlew assembleRelease without explicit error checking. If the Gradle build fails, the workflow continues to the APK signing step with a non-existent APK, causing confusing downstream failures.

Add explicit error handling or let the step fail fast:

       - name: Build APK
-        run: ./gradlew assembleRelease
+        run: |
+          ./gradlew assembleRelease
+          if [[ ! -f app/build/outputs/apk/release/app-release-unsigned.apk ]]; then
+            echo "Error: APK not found after build"
+            exit 1
+          fi

Alternatively, use set -e at the workflow level or rely on GitHub Actions' default set -e behavior for run steps (which should already fail on non-zero exit codes).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Build APK
run: ./gradlew assembleRelease
- name: Build APK
run: |
./gradlew assembleRelease
if [[ ! -f app/build/outputs/apk/release/app-release-unsigned.apk ]]; then
echo "Error: APK not found after build"
exit 1
fi
🤖 Prompt for AI Agents
In build/Android-deploy.yml around lines 63-64, the "Build APK" step runs
./gradlew assembleRelease but doesn't enforce a fail-fast behavior; update the
workflow so the Gradle step fails the job on non-zero exit (e.g., ensure run
steps use set -e or remove any continue-on-error), and add an explicit
post-build verification that the expected APK(s) exist (exit with non-zero and
log an error if missing) before proceeding to the signing step so downstream
steps never run against a nonexistent artifact.


# 🔏 Sign the generated APK
- name: Sign APK
uses: r0adkll/sign-android-release@v1
with:
releaseDirectory: app/build/outputs/apk/release
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
Comment on lines +68 to +74
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Recommended: Verify r0adkll/sign-android-release action is maintained.

The workflow uses the third-party action r0adkll/sign-android-release@v1. Verify that:

  1. The action is actively maintained and not deprecated.
  2. There are no known security issues or breaking changes.
  3. Consider pinning to a specific commit hash instead of a major version tag for reproducibility.

🌐 Web query:

Is r0adkll/sign-android-release action maintained and current?

💡 Result:

Short answer: No — it appears unmaintained and not current.

Evidence:

  • Latest release is v1 on Nov 7, 2019. [1]
  • The repo has open issues and PRs (examples: a reported breakage in Jan 2024), indicating users still hit problems but no recent release or maintainer response. [2]
  • The action is still listed on the Marketplace but without recent updates. [3]

If you rely on this in CI, consider using a maintained fork or an alternative action (or pin to a commit you vet).

Sources:
[1] r0adkll/sign-android-release (GitHub repo — releases).
[2] Issue "zipalign not found cause signing failure" opened Jan 10, 2024 (repo issues).
[3] "Sign Android release" (GitHub Marketplace entry).


Critical: r0adkll/sign-android-release@v1 is unmaintained and has known issues — replace or update.

The action's latest release is v1 from November 2019 and remains unmaintained. Users have reported breaking changes, including a zipalign failure issue in January 2024, with no recent maintainer response.

Recommended actions:

  1. Migrate to a maintained alternative or a maintained fork.
  2. If continuing with this action, pin to a specific verified commit hash rather than the v1 tag to improve reproducibility and control over potential breakage.


# 🧩 Rename APK with version for clarity
- name: Rename APK with version
run: |
VERSION=${{ steps.semantic.outputs.version }}
mkdir -p dist
cp app/build/outputs/apk/release/app-release-signed.apk dist/app-release-v${VERSION}.apk
echo "APK_NAME=app-release-v${VERSION}.apk" >> $GITHUB_ENV
Comment on lines +77 to +82
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Recommended: Validate signed APK exists and verify release directory.

After APK signing (line 68) and before renaming (line 77), add a verification step to confirm the signed APK exists:

       - name: Rename APK with version
         run: |
+          if [[ ! -f app/build/outputs/apk/release/app-release-signed.apk ]]; then
+            echo "Error: Signed APK not found"
+            exit 1
+          fi
           VERSION=${{ steps.semantic.outputs.version }}
           mkdir -p dist
           cp app/build/outputs/apk/release/app-release-signed.apk dist/app-release-v${VERSION}.apk
+          if [[ ! -f dist/app-release-v${VERSION}.apk ]]; then
+            echo "Error: Failed to copy APK to dist/"
+            exit 1
+          fi
           echo "APK_NAME=app-release-v${VERSION}.apk" >> $GITHUB_ENV
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Rename APK with version
run: |
VERSION=${{ steps.semantic.outputs.version }}
mkdir -p dist
cp app/build/outputs/apk/release/app-release-signed.apk dist/app-release-v${VERSION}.apk
echo "APK_NAME=app-release-v${VERSION}.apk" >> $GITHUB_ENV
- name: Rename APK with version
run: |
if [[ ! -f app/build/outputs/apk/release/app-release-signed.apk ]]; then
echo "Error: Signed APK not found"
exit 1
fi
VERSION=${{ steps.semantic.outputs.version }}
mkdir -p dist
cp app/build/outputs/apk/release/app-release-signed.apk dist/app-release-v${VERSION}.apk
if [[ ! -f dist/app-release-v${VERSION}.apk ]]; then
echo "Error: Failed to copy APK to dist/"
exit 1
fi
echo "APK_NAME=app-release-v${VERSION}.apk" >> $GITHUB_ENV
🤖 Prompt for AI Agents
In build/Android-deploy.yml around lines 77 to 82, the workflow blindly copies
the signed APK and sets APK_NAME without checking that
app/build/outputs/apk/release/app-release-signed.apk actually exists or that the
dist directory is ready; add a pre-check that verifies the signed APK file
exists and is readable and if not fail the step with a clear error message,
ensure the dist directory is created (mkdir -p dist) before copying, and only
then copy the file and set the GITHUB_ENV variable so the job fails fast and
provides a helpful error when signing/output path is missing.


# 🏷️ Run semantic-release to publish release and attach APK
- name: Run semantic-release and upload APK
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx semantic-release --assets "dist/${APK_NAME}"
Comment on lines +14 to +89
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Recommended: Add job concurrency control to prevent duplicate releases.

Multiple pushes to the main branch can trigger concurrent workflow runs, risking:

  1. Duplicate release versions or releases.
  2. Race conditions in semantic-release state.

Add concurrency control to serialize releases:

 jobs:
   release:
     name: 🚀 Semantic Release & Build
     runs-on: ubuntu-latest
+    concurrency:
+      group: android-release
+      cancel-in-progress: false
 
     steps:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
jobs:
release:
name: 🚀 Semantic Release & Build
runs-on: ubuntu-latest
steps:
# 🧩 Checkout the repository
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0
# ⚙️ Setup Node.js for release management
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
# 🧰 Install semantic-release and plugins
- name: Install release tools
run: |
npm install -g semantic-release \
@semantic-release/changelog \
@semantic-release/git \
@semantic-release/commit-analyzer \
@semantic-release/release-notes-generator \
@semantic-release/github
# 🏷️ Run semantic-release to manage versions
- name: Run semantic-release (dry-run to get next version)
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(npx semantic-release --dry-run | grep "The next release version is" | awk '{print $NF}')
echo "version=$VERSION" >> $GITHUB_OUTPUT || echo "version=0.0.0" >> $GITHUB_OUTPUT
# 🧱 Setup Java (required for Android build)
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
# 🧩 Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
# 🏗️ Build the APK (Release)
- name: Build APK
run: ./gradlew assembleRelease
# 🔏 Sign the generated APK
- name: Sign APK
uses: r0adkll/sign-android-release@v1
with:
releaseDirectory: app/build/outputs/apk/release
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
# 🧩 Rename APK with version for clarity
- name: Rename APK with version
run: |
VERSION=${{ steps.semantic.outputs.version }}
mkdir -p dist
cp app/build/outputs/apk/release/app-release-signed.apk dist/app-release-v${VERSION}.apk
echo "APK_NAME=app-release-v${VERSION}.apk" >> $GITHUB_ENV
# 🏷️ Run semantic-release to publish release and attach APK
- name: Run semantic-release and upload APK
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx semantic-release --assets "dist/${APK_NAME}"
jobs:
release:
name: 🚀 Semantic Release & Build
runs-on: ubuntu-latest
concurrency:
group: android-release
cancel-in-progress: false
steps:
# 🧩 Checkout the repository
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0
# ⚙️ Setup Node.js for release management
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
# 🧰 Install semantic-release and plugins
- name: Install release tools
run: |
npm install -g semantic-release \
@semantic-release/changelog \
@semantic-release/git \
@semantic-release/commit-analyzer \
@semantic-release/release-notes-generator \
@semantic-release/github
# 🏷️ Run semantic-release to manage versions
- name: Run semantic-release (dry-run to get next version)
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(npx semantic-release --dry-run | grep "The next release version is" | awk '{print $NF}')
echo "version=$VERSION" >> $GITHUB_OUTPUT || echo "version=0.0.0" >> $GITHUB_OUTPUT
# 🧱 Setup Java (required for Android build)
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
# 🧩 Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
# 🏗️ Build the APK (Release)
- name: Build APK
run: ./gradlew assembleRelease
# 🔏 Sign the generated APK
- name: Sign APK
uses: r0adkll/sign-android-release@v1
with:
releaseDirectory: app/build/outputs/apk/release
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
# 🧩 Rename APK with version for clarity
- name: Rename APK with version
run: |
VERSION=${{ steps.semantic.outputs.version }}
mkdir -p dist
cp app/build/outputs/apk/release/app-release-signed.apk dist/app-release-v${VERSION}.apk
echo "APK_NAME=app-release-v${VERSION}.apk" >> $GITHUB_ENV
# 🏷️ Run semantic-release to publish release and attach APK
- name: Run semantic-release and upload APK
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx semantic-release --assets "dist/${APK_NAME}"
🤖 Prompt for AI Agents
In build/Android-deploy.yml around lines 14 to 89, the workflow lacks
concurrency control which can allow concurrent runs to produce duplicate
semantic releases; add a concurrency stanza to the release job to serialize runs
(e.g. jobs.release.concurrency with a group that includes the ref or workflow
name like release-${{ github.ref }} and cancel-in-progress: true) so only one
release job runs per branch/ref and in-progress runs are cancelled when a new
run starts.

38 changes: 38 additions & 0 deletions deploy/Deploy-ssh.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Deploy to Infrastructure

on:
push:
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest

steps:
# Step 1: Checkout code
- name: Checkout code
uses: actions/checkout@v3

# Step 3: Deploy to Server
- name: 🌈 Deploy with SSH
uses: appleboy/ssh-action@v0.1.0
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
port: 22
script: |
echo "Starting deployment..."

# Check if the Git repository already exists, if not, clone it
if [ ! -d ".git" ]; then
echo "Git repository not found. Cloning repository..."
git clone ${{ secrets.REPO_URL }}
else
echo "Git repository found. Pulling the latest changes..."
cd Docker
git pull origin main
fi

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove trailing spaces.
Eliminate trailing whitespace on this line to satisfy lint rules.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 37-37: trailing spaces

(trailing-spaces)

🤖 Prompt for AI Agents
In deploy/Deploy-ssh.yml at line 37, remove any trailing whitespace characters
at the end of the line to comply with linting rules and maintain clean code
formatting.

echo "Deployment completed successfully."
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add newline at end of file.
Include a trailing newline to comply with POSIX and YAML linters.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 38-38: no new line character at the end of file

(new-line-at-end-of-file)

🤖 Prompt for AI Agents
In deploy/Deploy-ssh.yml at line 38, the file is missing a trailing newline at
the end. Add a newline character after the last line to comply with POSIX
standards and YAML linter requirements.

41 changes: 41 additions & 0 deletions deploy/aws/ecs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Deploy to Amazon ECS

on:
push:
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

Comment on lines +13 to +15
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Upgrade actions/checkout to v3 for consistency.
Other workflows adopt @v3 or @v4; bump to actions/checkout@v3 to use the latest stable features and security fixes.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 13-13: wrong indentation: expected 6 but found 4

(indentation)

🤖 Prompt for AI Agents
In deploy/aws/ecs.yml around lines 13 to 15, the GitHub Actions step uses
actions/checkout@v2, which is outdated. Update the version to
actions/checkout@v3 to align with other workflows and benefit from the latest
stable features and security improvements.

Comment on lines +12 to +15
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix YAML indentation under steps.
Step items must be indented two spaces under steps: (6 spaces total). Apply this diff:

-    steps:
-    - name: Checkout code
+    steps:
+      - name: Checkout code
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
steps:
- name: Checkout code
uses: actions/checkout@v2
steps:
- name: Checkout code
uses: actions/checkout@v2
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 13-13: wrong indentation: expected 6 but found 4

(indentation)

🤖 Prompt for AI Agents
In deploy/aws/ecs.yml around lines 12 to 15, the step items under the `steps:`
key are not indented correctly. Fix the YAML indentation by ensuring each step
item is indented two spaces more than the `steps:` key, resulting in a total of
6 spaces before each step item line.

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build and push Docker Compose services to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker-compose build
docker-compose push

- name: Deploy to Amazon ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ env.ECS_TASK_DEFINITION }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add newline at end of file.
Include a final newline to satisfy the no new line character at end of file lint error.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 41-41: no new line character at the end of file

(new-line-at-end-of-file)

🤖 Prompt for AI Agents
In deploy/aws/ecs.yml at line 41, the file is missing a newline character at the
end, causing a lint error. Add a single newline character after the last line to
ensure the file ends with a proper newline.

Loading