feat(ui): 添加应用内使用指南 #6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release on Version Bump | |
| on: | |
| push: | |
| branches: [ "main", "master" ] | |
| paths: | |
| - 'app/build.gradle' | |
| - 'app/build.gradle.kts' | |
| - 'gradle.properties' | |
| - 'app/src/main/AndroidManifest.xml' | |
| workflow_dispatch: {} | |
| concurrency: | |
| group: release-on-version-bump | |
| cancel-in-progress: false | |
| jobs: | |
| release: | |
| name: Build and Release | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Java 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '17' | |
| cache: 'gradle' | |
| - name: Validate Gradle Wrapper (non-blocking) | |
| uses: gradle/wrapper-validation-action@v2 | |
| continue-on-error: true | |
| timeout-minutes: 2 | |
| - name: Set up Gradle | |
| uses: gradle/actions/setup-gradle@v3 | |
| - name: Detect version change | |
| id: version | |
| env: | |
| GITHUB_EVENT_BEFORE: ${{ github.event.before }} | |
| run: | | |
| python3 - <<'PY' | |
| import os, re, subprocess | |
| def read_file(path): | |
| try: | |
| with open(path, 'r', encoding='utf-8') as f: | |
| return f.read() | |
| except FileNotFoundError: | |
| return None | |
| def parse_versions(text): | |
| if not text: | |
| return None, None | |
| vn = None | |
| vc = None | |
| m = re.search(r'versionName\s*[= ]\s*"?([0-9A-Za-z\.-_\+]+)"?', text) | |
| if m: | |
| vn = m.group(1) | |
| m = re.search(r'versionCode\s*[= ]\s*"?([0-9]+)"?', text) | |
| if m: | |
| vc = m.group(1) | |
| if vn is None: | |
| m = re.search(r'(?im)^\s*(?:VERSION_NAME|versionName)\s*=\s*([^\s#]+)', text) | |
| if m: | |
| vn = m.group(1).strip() | |
| if vc is None: | |
| m = re.search(r'(?im)^\s*(?:VERSION_CODE|versionCode)\s*=\s*([0-9]+)', text) | |
| if m: | |
| vc = m.group(1).strip() | |
| if vn is None: | |
| m = re.search(r'android:versionName\s*=\s*"([^"]+)"', text) | |
| if m: | |
| vn = m.group(1) | |
| if vc is None: | |
| m = re.search(r'android:versionCode\s*=\s*"([^"]+)"', text) | |
| if m: | |
| vc = m.group(1) | |
| return vn, vc | |
| def get_file_at_rev(path, rev=None): | |
| if rev is None: | |
| return read_file(path) | |
| try: | |
| out = subprocess.check_output(['git', 'show', f'{rev}:{path}'], stderr=subprocess.STDOUT) | |
| return out.decode('utf-8', errors='ignore') | |
| except subprocess.CalledProcessError: | |
| return None | |
| paths = ['app/build.gradle', 'app/build.gradle.kts', 'gradle.properties', 'app/src/main/AndroidManifest.xml'] | |
| text_head = None | |
| for p in paths: | |
| content = get_file_at_rev(p, None) | |
| if content: | |
| text_head = content | |
| break | |
| vn_head, vc_head = parse_versions(text_head) | |
| prev_rev = os.environ.get('GITHUB_EVENT_BEFORE') or 'HEAD^' | |
| text_prev = None | |
| for p in paths: | |
| content = get_file_at_rev(p, prev_rev) | |
| if content: | |
| text_prev = content | |
| break | |
| vn_prev, vc_prev = parse_versions(text_prev) | |
| changed = False | |
| if vn_head and (vn_head != (vn_prev or '')): | |
| changed = True | |
| elif vc_head and (vc_head != (vc_prev or '')): | |
| changed = True | |
| with open(os.environ['GITHUB_OUTPUT'], 'a') as f: | |
| f.write(f'version_name={vn_head or ""}\n') | |
| f.write(f'version_code={vc_head or ""}\n') | |
| f.write(f'changed={"true" if changed else "false"}\n') | |
| PY | |
| - name: Stop if version didn't change | |
| if: steps.version.outputs.changed != 'true' | |
| run: | | |
| echo "Version did not change. Skipping release." | |
| exit 0 | |
| - name: Set up Android SDK | |
| uses: android-actions/setup-android@v3 | |
| with: | |
| api-level: 34 | |
| build-tools: 34.0.0 | |
| - name: Make Gradle wrapper executable | |
| run: | | |
| chmod +x ./gradlew || true | |
| sed -i -e 's/\r$//' ./gradlew || true | |
| - name: Build debug APK (no signing keys required) | |
| run: ./gradlew --no-daemon clean assembleDebug | |
| continue-on-error: true | |
| - name: Locate built APK (if any) | |
| id: locate_apk | |
| run: | | |
| APK_PATH=$(ls app/build/outputs/apk/debug/*.apk 2>/dev/null || true) | |
| if [ -n "$APK_PATH" ]; then | |
| echo "apk_path=$APK_PATH" >> "$GITHUB_OUTPUT" | |
| echo "Found APK: $APK_PATH" | |
| else | |
| echo "apk_path=" >> "$GITHUB_OUTPUT" | |
| echo "No APK built; will release notes only." | |
| fi | |
| - name: Compose tag | |
| id: tag | |
| run: | | |
| V="${{ steps.version.outputs.version_name }}" | |
| if [ -z "$V" ]; then V="${{ steps.version.outputs.version_code }}"; fi | |
| if [ -z "$V" ]; then V="$(date +%Y%m%d)-${{ github.sha }}"; fi | |
| echo "tag=v$V" >> "$GITHUB_OUTPUT" | |
| echo "version_display=$V" >> "$GITHUB_OUTPUT" | |
| - name: Create GitHub release (with APK) | |
| if: steps.locate_apk.outputs.apk_path != '' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.tag }} | |
| name: ${{ steps.tag.outputs.tag }} | |
| generate_release_notes: true | |
| files: ${{ steps.locate_apk.outputs.apk_path }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Create GitHub release (notes only) | |
| if: steps.locate_apk.outputs.apk_path == '' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.tag }} | |
| name: ${{ steps.tag.outputs.tag }} | |
| generate_release_notes: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |