Skip to content
Merged
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
30 changes: 22 additions & 8 deletions .github/workflows/desktop-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -757,19 +757,17 @@ jobs:
run: |
set -euo pipefail
shopt -s globstar
# AppImage, deb, and rpm files are already copied into the
# canonical release-updater-assets directory above. Publishing the
# raw Tauri bundle names as well creates a second public copy of
# every Linux installer and doubles the signature count.
node scripts/stage-github-release-assets.mjs \
--out-dir release-upload-assets \
release-updater-assets/* \
release-manual-assets/*.exe \
release-manual-assets/*.exe.sig \
release-assets/**/*.AppImage \
release-assets/**/*.AppImage.sig \
release-assets/**/*.deb \
release-assets/**/*.deb.sig \
release-assets/**/*.dmg \
release-assets/**/*.dmg.sig \
release-assets/**/*.rpm \
release-assets/**/*.rpm.sig \
release-assets/minisign.pub \
linux-release-assets/openbitfun-cli-*.tar.gz \
linux-release-assets/openbitfun-cli-*.tar.gz.sha256 \
Expand Down Expand Up @@ -827,9 +825,25 @@ jobs:
esac
gh release upload "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" \
--clobber release-upload-assets/*
MOBILE_VERSION="$(sed -nE 's/.*versionName = "([^"]+)".*/\1/p' \
src/apps/mobile/android/app/build.gradle.kts 2>/dev/null | head -n1 || true)"
MOBILE_VERSION="${MOBILE_VERSION:-$RELEASE_VERSION}"
gh release view "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" \
--json body --jq .body > release-notes.md
if ! grep -q '<!-- openbitfun-mobile-release -->' release-notes.md; then
cat >> release-notes.md <<EOF

<!-- openbitfun-mobile-release -->
### Android mobile

Android mobile version **${MOBILE_VERSION}** is published separately as a prerelease:
[Download the Android prerelease](https://github.com/${GITHUB_REPOSITORY}/releases/tag/mobile-v${MOBILE_VERSION}).
The current APK uses the runner-generated debug signing key.
EOF
fi
gh release edit "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" \
--title "OpenBitFun ${RELEASE_VERSION}" --draft=false \
--prerelease="${RELEASE_PRERELEASE}" --latest="${RELEASE_LATEST}"
--title "OpenBitFun ${RELEASE_VERSION}" --notes-file release-notes.md \
--draft=false --prerelease="${RELEASE_PRERELEASE}" --latest="${RELEASE_LATEST}"

- name: Verify published legacy update feeds
if: needs.prepare.outputs.release_channel == 'stable'
Expand Down
133 changes: 133 additions & 0 deletions .github/workflows/mobile-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
name: Mobile Package

on:
push:
tags:
- 'mobile-v*'
workflow_dispatch:
inputs:
tag_name:
description: 'Mobile release tag (for example mobile-v1.0.0).'
required: true
type: string

permissions:
contents: write

concurrency:
group: mobile-package-${{ github.event.release.tag_name || inputs.tag_name || github.ref_name }}
cancel-in-progress: false

jobs:
prepare:
name: Prepare mobile release
runs-on: ubuntu-latest
outputs:
tag_name: ${{ steps.meta.outputs.tag_name }}
version: ${{ steps.meta.outputs.version }}
prerelease: ${{ steps.meta.outputs.prerelease }}
steps:
- uses: actions/checkout@v5
with:
ref: ${{ inputs.tag_name || github.ref_name }}
fetch-depth: 1

- name: Resolve mobile version
id: meta
shell: bash
env:
INPUT_TAG_NAME: ${{ inputs.tag_name }}
REF_NAME: ${{ github.ref_name }}
run: |
set -euo pipefail
TAG="${INPUT_TAG_NAME:-${REF_NAME}}"
case "$TAG" in
mobile-v*) ;;
*) echo "Expected a mobile-v* tag, got $TAG" >&2; exit 1 ;;
esac
VERSION="${TAG#mobile-v}"
node scripts/verify-release-version-sync.mjs --mobile-version "$VERSION"
if [[ "$VERSION" == *-* ]]; then
PRERELEASE=true
else
PRERELEASE=false
fi
printf 'tag_name=%s\nversion=%s\nprerelease=%s\n' \
"$TAG" "$VERSION" "$PRERELEASE" >> "$GITHUB_OUTPUT"

android:
name: Android package
needs: prepare
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
ref: ${{ needs.prepare.outputs.tag_name }}

- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '21'

- uses: gradle/actions/setup-gradle@v4

- name: Configure Android release signing
shell: bash
run: |
set -euo pipefail
echo "Using the runner-generated Android debug keystore for this mobile prerelease."

- name: Build signed Android package
working-directory: src/apps/mobile/android
run: ./gradlew :app:assembleRelease --no-daemon

- name: Stage Android release assets
shell: bash
env:
VERSION: ${{ needs.prepare.outputs.version }}
run: |
set -euo pipefail
mkdir -p mobile-release-assets
suffix='-debug'
cp src/apps/mobile/android/app/build/outputs/apk/release/app-release.apk \
"mobile-release-assets/OpenBitFun-Mobile-${VERSION}-android${suffix}.apk"
(cd mobile-release-assets && sha256sum ./*.apk > SHA256SUMS)

- uses: actions/upload-artifact@v6
with:
name: openbitfun-mobile-${{ needs.prepare.outputs.tag_name }}-android
path: mobile-release-assets/*
if-no-files-found: error
retention-days: 7

publish:
name: Publish mobile release
needs: [prepare, android]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
ref: ${{ needs.prepare.outputs.tag_name }}

- uses: actions/download-artifact@v7
with:
name: openbitfun-mobile-${{ needs.prepare.outputs.tag_name }}-android
path: mobile-release-assets

- name: Create mobile release
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ needs.prepare.outputs.tag_name }}
VERSION: ${{ needs.prepare.outputs.version }}
PRERELEASE: true
shell: bash
run: |
set -euo pipefail
VERSION="$VERSION (debug signing)"
gh release create "$TAG_NAME" \
--repo "$GITHUB_REPOSITORY" \
--verify-tag \
--title "OpenBitFun Mobile $VERSION" \
--generate-notes \
--prerelease="$PRERELEASE" \
mobile-release-assets/*
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ OpenBitFun is a highly customizable, open-source agent workspace that keeps work

**If this is the kind of agent workspace you want, ⭐ Star OpenBitFun and help more people discover it.**

[Download](https://openbitfun.com/download) · [Mini App Marketplace](https://market.openbitfun.com/miniapp/) · [Contribute](./CONTRIBUTING.md)
[Download Desktop](https://openbitfun.com/download) · [Mobile Releases](https://github.com/GCWing/OpenBitFun/releases?q=mobile-&expanded=true) · [Mini App Marketplace](https://market.openbitfun.com/miniapp/) · [Contribute](./CONTRIBUTING.md)

[![Website](https://img.shields.io/badge/Website-openbitfun.com-0b7285?style=flat-square)](https://openbitfun.com/)
[![Core code: MIT](https://img.shields.io/badge/core_code-MIT-yellow?style=flat-square)](./LICENSE)
Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ OpenBitFun 是一个高度可定制的开源 Agent 工作台,让任务按你

**如果你也期待这样的 Agent,欢迎点亮 ⭐ Star,让更多人发现 OpenBitFun。**

[下载体验](https://openbitfun.com/zh/download) · [Mini App 市场](https://market.openbitfun.com/miniapp/) · [参与共建](./CONTRIBUTING_CN.md)
[下载桌面端](https://openbitfun.com/zh/download) · [移动端 Release](https://github.com/GCWing/OpenBitFun/releases?q=mobile-&expanded=true) · [Mini App 市场](https://market.openbitfun.com/miniapp/) · [参与共建](./CONTRIBUTING_CN.md)

[![官网](https://img.shields.io/badge/%E5%AE%98%E7%BD%91-openbitfun.com-0b7285?style=flat-square)](https://openbitfun.com/zh)
[![Core code: MIT](https://img.shields.io/badge/core_code-MIT-yellow?style=flat-square)](./LICENSE)
Expand Down
16 changes: 16 additions & 0 deletions docs/development/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ its tag automatically. Release creation and editing use GitHub CLI without
`--target`: sending `target_commitish` for workflow-changing commits can require
`workflows:write`, even for an existing tag. Asset upload precedes publication.

## Mobile Android releases

Mobile Android packages are released independently from Desktop packages. Use a
`mobile-vMAJOR.MINOR.PATCH` tag (or a prerelease suffix such as
`mobile-v1.1.0-beta.1`) to trigger [`Mobile Package`](../../.github/workflows/mobile-package.yml).
The workflow builds an Android APK with the runner-generated debug keystore and
publishes it to its own prerelease GitHub Release. It does not add Android assets
to the Desktop `v*` Release. A production signing key can be introduced later
without changing the mobile tag or release layout. Mobile Android versions are
checked as a group across the Android, iOS, and HarmonyOS version files, but they
do not need to equal the Desktop version.

GitHub exposes one repository-wide `Latest` release. Desktop release notes also
include the Android version and a link to the corresponding Mobile prerelease,
while the Desktop release itself contains no Android APK assets.

## Legacy update isolation

Desktop 1.x reads `latest-v1.json`; CLI 1.x reads `linux-binaries-v1.json`,
Expand Down
36 changes: 36 additions & 0 deletions scripts/check-github-config.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,10 +1094,46 @@ test('stages unique release asset names before publishing', () => {
/release-assets\/\*\*\/\*\.sig(?:\s|\\)/,
'raw updater signatures have colliding names across macOS architectures',
);
assert.doesNotMatch(
steps[stagingIndex].run,
/release-assets\/\*\*\/\*(?:\.AppImage|\.deb|\.rpm)(?:\s|\\)/,
'raw Linux bundles must not duplicate canonical updater assets in the public release',
);
}
assert.match(steps[uploadIndex].run, /--clobber release-upload-assets\/\*/);
});

test('Desktop release notes link the separately published Android prerelease', () => {
const workflow = yaml.parse(
readFileSync(
path.join(repoRoot, '.github/workflows/desktop-package.yml'),
'utf8',
),
);
const uploadStep = workflow.jobs['upload-release-assets'].steps.find(
(step) => step.name === 'Upload to release',
);
assert.match(uploadStep.run, /mobile-v\$\{MOBILE_VERSION\}/);
assert.match(uploadStep.run, /runner-generated debug signing key/);
assert.match(uploadStep.run, /--notes-file release-notes\.md/);
});

test('Mobile Package publishes Android assets from mobile-v tags', () => {
const workflow = yaml.parse(
readFileSync(path.join(repoRoot, '.github/workflows/mobile-package.yml'), 'utf8'),
);
assert.ok(workflow.on.push.tags.includes('mobile-v*'));
assert.match(
workflow.jobs.android.steps.find((step) => step.name === 'Build signed Android package').run,
/:app:assembleRelease/,
);
assert.equal(workflow.jobs.publish.needs.includes('android'), true);
assert.match(
workflow.jobs.publish.steps.find((step) => step.name === 'Create mobile release').run,
/gh release create/,
);
});

test('Desktop packaging installs Bun before preparing the OpenCode extension Host', () => {
const workflow = yaml.parse(
readFileSync(path.join(repoRoot, '.github/workflows/desktop-package.yml'), 'utf8'),
Expand Down
Loading