Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
215ece2
try to build android apk
o-murphy Apr 23, 2026
4afee6e
fix: generate public ca-cert
o-murphy Apr 23, 2026
b16c326
fix: --split-per-abi
o-murphy Apr 23, 2026
88c61b4
seems: running on android
o-murphy Apr 23, 2026
0b9467b
fix: fixed android issues
o-murphy Apr 24, 2026
6d13790
fix: imnport data: file picker
o-murphy Apr 24, 2026
b22192e
workaround: IMPELER IS DISABLED FOR ANDROID
o-murphy Apr 24, 2026
0159e69
fix: error message on invalid filetype
o-murphy Apr 24, 2026
aad8be8
add: android keystore and self-signing
o-murphy Apr 24, 2026
44883f2
updated: apk namespace and applicationId
o-murphy Apr 24, 2026
603b7a0
feat: database resilience
o-murphy Apr 24, 2026
c773c8e
Input adjustments in clicks
o-murphy Apr 24, 2026
31dfe9a
attempt to fix adjustment display and provede zero offsets
o-murphy Apr 24, 2026
4c6c9c8
fix: adjustments display, window scale factor
o-murphy Apr 24, 2026
c40bd57
update: Ammo entity separate zeroOffset units
o-murphy Apr 24, 2026
58f72d2
update: Ammo entity separate zeroOffset units
o-murphy Apr 24, 2026
42553f0
fix: attempt to fix reactivity flow
o-murphy Apr 24, 2026
60ead2d
add: reusable fields
o-murphy Apr 24, 2026
4c095c8
issue: the app state provider do not work properly
o-murphy Apr 24, 2026
c75ff74
fix: unwaitable from ammo wizrd route
o-murphy Apr 24, 2026
155f213
fix: unwaitable from ammo wizrd route
o-murphy Apr 24, 2026
9c8557f
docs: updated CHANGELOG.md and backlog
o-murphy Apr 24, 2026
18a8ad5
removed useless assets
o-murphy Apr 24, 2026
28efad6
update: reticles generator
o-murphy Apr 24, 2026
dc645ca
update: reticles generator
o-murphy Apr 24, 2026
2367ff3
docs: updated CHANGELOG.md and backlog
o-murphy Apr 24, 2026
e2f9ebc
bump: package version
o-murphy Apr 24, 2026
ea7e514
update: readme, workflows, screenshots
o-murphy Apr 25, 2026
465f6f9
update: CHANGELOG, build.yml
o-murphy Apr 25, 2026
aa46893
update: CHANGELOG, build.yml
o-murphy Apr 25, 2026
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
10 changes: 2 additions & 8 deletions .github/actions/version/action.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
name: "Resolve version"
description: "Extracts version from tag (v1.2.3 → 1.2.3) or returns a default for non-tag runs"

inputs:
default:
description: "Version to use when not running on a tag"
required: false
default: "0.1.0-dev"
description: "Extracts version from tag (v1.2.3 → 1.2.3) or reads base version from pubspec.yaml"

outputs:
version:
Expand All @@ -22,7 +16,7 @@ runs:
VERSION="${{ github.ref_name }}"
[[ "${VERSION}" == v* ]] && VERSION="${VERSION:1}"
else
VERSION="${{ inputs.default }}"
VERSION=$(grep '^version:' pubspec.yaml | sed 's/version:[[:space:]]*//' | sed 's/+.*//')
fi
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "Resolved version: ${VERSION}"
187 changes: 187 additions & 0 deletions .github/workflows/build-apk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
name: Build Android APK

on:
workflow_call:
inputs:
build_name:
description: "Version name (e.g. v1.2.3)"
required: false
type: string
default: ""
build_type:
description: "Build type"
required: false
type: string
default: "release"
retention_days:
description: "Artifact retention in days"
required: false
type: number
default: 30
secrets:
ANDROID_KEYSTORE_BASE64:
description: "Base64-encoded Android keystore (.jks / .p12)"
required: false
ANDROID_KEYSTORE_PASSWORD:
description: "Keystore store password"
required: false
ANDROID_KEY_ALIAS:
description: "Key alias inside the keystore"
required: false
ANDROID_KEY_PASSWORD:
description: "Key password"
required: false
outputs:
artifact_name:
description: "Name of the uploaded artifact"
value: ${{ jobs.build.outputs.artifact_name }}
artifact_url:
description: "URL to the artifact"
value: ${{ jobs.build.outputs.artifact_url }}

workflow_dispatch:
inputs:
build_name:
description: "Version name override (leave empty to use pubspec.yaml)"
required: false
default: ""
type: string
build_type:
description: "Build type"
required: false
default: "release"
type: choice
options: [ release, debug ]

pull_request:
branches: [ main, develop ]
paths:
- "lib/**"
- "android/**"
- "external/**"
- "packages/bclibc_ffi/**"
- "pubspec.yaml"
- "scripts/build-android.sh"
- ".github/workflows/build-apk.yml"

env:
FLUTTER_VERSION: "3.41.6"

jobs:
prepare-version:
runs-on: ubuntu-latest
if: github.event_name != 'workflow_call'
outputs:
version: ${{ steps.v.outputs.version }}
steps:
- uses: actions/checkout@v4
- id: v
uses: ./.github/actions/version

build:
needs: [ prepare-version ]
if: always()
name: Android APK (${{ inputs.build_type || 'release' }})
runs-on: ubuntu-latest
outputs:
artifact_name: ${{ steps.meta.outputs.artifact_name }}
artifact_url: ${{ steps.upload.outputs.artifact-url }}

steps:
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"

- name: Setup Flutter
uses: ./.github/actions/flutter
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true

- name: Accept Android licenses
run: yes | flutter doctor --android-licenses || true

- name: Set build metadata
id: meta
shell: bash
run: |
BUILD_NAME="${{ inputs.build_name || needs.prepare-version.outputs.version }}"
BUILD_NAME="${BUILD_NAME#v}"
BUILD_NUMBER="${{ github.run_number }}"
BCLIBC_HASH=$(git -C external/bclibc rev-parse HEAD)
BCLIBC_FFI_HASH=$(git log -1 --format='%H' -- packages/bclibc_ffi 2>/dev/null || echo "unknown")
echo "build_name=$BUILD_NAME" >> $GITHUB_OUTPUT
echo "build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT
echo "bclibc_hash=$BCLIBC_HASH" >> $GITHUB_OUTPUT
echo "bclibc_ffi_hash=$BCLIBC_FFI_HASH" >> $GITHUB_OUTPUT
echo "artifact_name=ebalistyka-android-${{ inputs.build_type || 'release' }}-${BUILD_NAME}-${BUILD_NUMBER}" >> $GITHUB_OUTPUT

- name: Cache pub packages
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/pub-cache
key: pub-android-${{ hashFiles('pubspec.lock') }}
restore-keys: pub-android-

- name: Cache Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ hashFiles('android/app/build.gradle.kts', 'android/gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: gradle-

- name: Cache bclibc NDK build
uses: actions/cache@v4
with:
path: packages/bclibc_ffi/android/.cxx
key: bclibc-android-${{ steps.meta.outputs.bclibc_hash }}-${{ steps.meta.outputs.bclibc_ffi_hash }}
restore-keys: |
bclibc-android-${{ steps.meta.outputs.bclibc_hash }}-
bclibc-android-

- name: Install Flutter dependencies
run: |
flutter clean
flutter pub get

- name: Build & sign APKs
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: |
bash scripts/build-android.sh \
"${{ steps.meta.outputs.build_name }}" \
"${{ steps.meta.outputs.build_number }}"

- name: Upload artifact
id: upload
uses: actions/upload-artifact@v4
with:
name: ${{ steps.meta.outputs.artifact_name }}
path: artifacts/
retention-days: ${{ inputs.retention_days || 30 }}
if-no-files-found: error


pr-summary:
needs: [ build ]
if: always() && github.event_name == 'pull_request'
permissions:
pull-requests: write
issues: write
uses: ./.github/workflows/pr-summary.yml
with:
platform: Android
build_result: ${{ needs.build.result }}
artifact_name: ${{ needs.build.outputs.artifact_name }}
artifact_url: ${{ needs.build.outputs.artifact_url }}
106 changes: 21 additions & 85 deletions .github/workflows/build-appimage.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: PR Build (Linux AppImage)
name: Build Linux AppImage + Portable

on:
pull_request:
Expand Down Expand Up @@ -45,92 +45,28 @@ jobs:
build_name: ${{ needs.prepare-version.outputs.version }}
retention_days: 30

pr-summary:
name: PR Build Summary
runs-on: ubuntu-latest
needs: [ build-amd64, build-arm64 ]
pr-summary-amd64:
needs: [ build-amd64 ]
if: always() && github.event_name == 'pull_request'
permissions:
pull-requests: write
issues: write
uses: ./.github/workflows/pr-summary.yml
with:
platform: Linux amd64
build_result: ${{ needs.build-amd64.result }}
artifact_name: ${{ needs.build-amd64.outputs.artifact_name }}
artifact_url: ${{ needs.build-amd64.outputs.artifact_url }}

steps:
- name: Get PR number
id: pr
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
else
echo "number=" >> $GITHUB_OUTPUT
fi

- name: Comment on PR
if: steps.pr.outputs.number != ''
uses: actions/github-script@v7
with:
script: |
const prNumber = parseInt('${{ steps.pr.outputs.number }}');
const amd64Success = '${{ needs.build-amd64.result }}' === 'success';
const arm64Success = '${{ needs.build-arm64.result }}' === 'success';
const artifactUrl = '${{ needs.build-amd64.outputs.artifact_url || needs.build-arm64.outputs.artifact_url }}';
const artifactName = '${{ needs.build-amd64.outputs.artifact_name || needs.build-arm64.outputs.artifact_name }}';
const runUrl = `https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}`;

let body = `## Linux AppImage Build\n\n`;

if (amd64Success || arm64Success) {
body += `✅ **Build successful!**\n\n`;
body += `- **amd64**: ${amd64Success ? '✅' : '❌'}\n`;
body += `- **arm64**: ${arm64Success ? '✅' : '❌'}\n\n`;

if (artifactUrl) {
body += `📦 **[Download AppImage](${artifactUrl})**\n`;
body += `\`${artifactName}\` — available for 7 days\n\n`;
}

body += `**PR**: #${prNumber} · **Commit**: \`${{ github.sha }}\`\n\n`;
body += `### Test Instructions:\n`;
body += `\`\`\`bash\n# Download and run\nchmod +x ebalistyka-x86_64.AppImage\n./ebalistyka-x86_64.AppImage\n\`\`\`\n`;
} else {
body += `❌ **Build failed!**\n\n[View logs](${runUrl})\n`;
}

try {
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});

const existing = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('## Linux AppImage Build')
);

if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
}
} catch (error) {
console.log('Error posting comment:', error.message);
}

- name: Display build status
if: steps.pr.outputs.number == ''
run: |
echo "========================================="
echo "Build completed with status: ${{ needs.build-amd64.result }} / ${{ needs.build-arm64.result }}"
echo "========================================="
echo "Skipping PR comment because this is not a pull request event"
echo "Triggered by: ${{ github.event_name }}"
echo "Run URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
pr-summary-arm64:
needs: [ build-arm64 ]
if: always() && github.event_name == 'pull_request'
permissions:
pull-requests: write
issues: write
uses: ./.github/workflows/pr-summary.yml
with:
platform: Linux arm64
build_result: ${{ needs.build-arm64.result }}
artifact_name: ${{ needs.build-arm64.outputs.artifact_name }}
artifact_url: ${{ needs.build-arm64.outputs.artifact_url }}
Loading
Loading