feat(progress): extend inline progress fill to list mode and drop lin… #114
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: Publish | |
| on: | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: write | |
| jobs: | |
| detect: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| marketing_version: ${{ steps.version.outputs.marketing }} | |
| build_number: ${{ steps.version.outputs.build }} | |
| base_marketing_version: ${{ steps.changed.outputs.base_marketing }} | |
| base_build_number: ${{ steps.changed.outputs.base_build }} | |
| build_changed: ${{ steps.changed.outputs.build_changed }} | |
| marketing_changed: ${{ steps.changed.outputs.marketing_changed }} | |
| create_release: ${{ steps.changed.outputs.create_release }} | |
| release_version: ${{ steps.changed.outputs.release_version }} | |
| release_sha: ${{ steps.changed.outputs.release_sha }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Read versions | |
| id: version | |
| run: | | |
| set -euo pipefail | |
| FILE="Bangumi.xcodeproj/project.pbxproj" | |
| if [ ! -f "$FILE" ]; then | |
| echo "project.pbxproj not found at $FILE" >&2 | |
| exit 1 | |
| fi | |
| MARKETING=$(awk 'match($0,/MARKETING_VERSION = ([^;]+);/,a){gsub(/"/,"",a[1]); print a[1]; exit}' "$FILE") | |
| BUILD=$(awk 'match($0,/CURRENT_PROJECT_VERSION = ([^;]+);/,a){gsub(/"/,"",a[1]); print a[1]; exit}' "$FILE") | |
| if [ -z "$MARKETING" ]; then | |
| echo "MARKETING_VERSION not found in $FILE" >&2 | |
| exit 1 | |
| fi | |
| if [ -z "$BUILD" ]; then | |
| echo "CURRENT_PROJECT_VERSION not found in $FILE" >&2 | |
| exit 1 | |
| fi | |
| echo "Detected MARKETING_VERSION: $MARKETING" | |
| echo "Detected CURRENT_PROJECT_VERSION: $BUILD" | |
| { | |
| echo "marketing=$MARKETING" | |
| echo "build=$BUILD" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Detect version changes | |
| id: changed | |
| run: | | |
| set -euo pipefail | |
| FILE="Bangumi.xcodeproj/project.pbxproj" | |
| BASE="${{ github.event.before }}" | |
| HEAD="${{ github.sha }}" | |
| HEAD_MARKETING="${{ steps.version.outputs.marketing }}" | |
| if [ -z "$BASE" ] || [ "$BASE" = "0000000000000000000000000000000000000000" ]; then | |
| if git rev-parse "${HEAD}^" >/dev/null 2>&1; then | |
| BASE="$(git rev-parse "${HEAD}^")" | |
| else | |
| BASE="" | |
| fi | |
| fi | |
| read_project_value() { | |
| local source="$1" | |
| local key="$2" | |
| if [ "$source" = "WORKTREE" ]; then | |
| awk -v key="$key" '$0 ~ key " = " { sub(".*" key " = ", "", $0); sub(";.*", "", $0); gsub(/"/, "", $0); print $0; exit }' "$FILE" | |
| else | |
| git show "$source:$FILE" | awk -v key="$key" '$0 ~ key " = " { sub(".*" key " = ", "", $0); sub(";.*", "", $0); gsub(/"/, "", $0); print $0; exit }' | |
| fi | |
| } | |
| parse_major_minor() { | |
| local version="$1" | |
| local prefix="$2" | |
| if [[ "$version" =~ ^([0-9]+)\.([0-9]+)$ ]]; then | |
| printf -v "${prefix}_MAJOR" "%s" "${BASH_REMATCH[1]}" | |
| printf -v "${prefix}_MINOR" "%s" "${BASH_REMATCH[2]}" | |
| return 0 | |
| fi | |
| return 1 | |
| } | |
| BUILD_CHANGED=false | |
| MARKETING_CHANGED=false | |
| CREATE_RELEASE=false | |
| BASE_MARKETING="" | |
| BASE_BUILD="" | |
| RELEASE_VERSION="" | |
| RELEASE_SHA="" | |
| if [ -n "$BASE" ] && git cat-file -e "$BASE"^{commit} 2>/dev/null; then | |
| BASE_MARKETING="$(read_project_value "$BASE" MARKETING_VERSION)" | |
| BASE_BUILD="$(read_project_value "$BASE" CURRENT_PROJECT_VERSION)" | |
| DIFF=$(git diff "$BASE" "$HEAD" -- "$FILE" || true) | |
| if echo "$DIFF" | grep -q 'CURRENT_PROJECT_VERSION'; then | |
| BUILD_CHANGED=true | |
| fi | |
| if echo "$DIFF" | grep -q 'MARKETING_VERSION'; then | |
| MARKETING_CHANGED=true | |
| fi | |
| if [ "$MARKETING_CHANGED" = true ] \ | |
| && parse_major_minor "$BASE_MARKETING" BASE_VERSION \ | |
| && parse_major_minor "$HEAD_MARKETING" HEAD_VERSION; then | |
| if [ "$BASE_VERSION_MAJOR" -eq "$HEAD_VERSION_MAJOR" ] \ | |
| && [ "$HEAD_VERSION_MINOR" -eq $((BASE_VERSION_MINOR + 1)) ]; then | |
| CREATE_RELEASE=true | |
| RELEASE_VERSION="$BASE_MARKETING" | |
| RELEASE_SHA="$BASE" | |
| fi | |
| fi | |
| else | |
| BUILD_CHANGED=true | |
| MARKETING_CHANGED=true | |
| fi | |
| echo "Base MARKETING_VERSION: ${BASE_MARKETING:-unknown}" | |
| echo "Base CURRENT_PROJECT_VERSION: ${BASE_BUILD:-unknown}" | |
| echo "Create delayed release: $CREATE_RELEASE" | |
| if [ "$CREATE_RELEASE" = true ]; then | |
| echo "Release target: v$RELEASE_VERSION at $RELEASE_SHA" | |
| fi | |
| echo "base_marketing=$BASE_MARKETING" >> "$GITHUB_OUTPUT" | |
| echo "base_build=$BASE_BUILD" >> "$GITHUB_OUTPUT" | |
| echo "build_changed=$BUILD_CHANGED" >> "$GITHUB_OUTPUT" | |
| echo "marketing_changed=$MARKETING_CHANGED" >> "$GITHUB_OUTPUT" | |
| echo "create_release=$CREATE_RELEASE" >> "$GITHUB_OUTPUT" | |
| echo "release_version=$RELEASE_VERSION" >> "$GITHUB_OUTPUT" | |
| echo "release_sha=$RELEASE_SHA" >> "$GITHUB_OUTPUT" | |
| release: | |
| runs-on: ubuntu-latest | |
| needs: detect | |
| if: needs.detect.outputs.create_release == 'true' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Ensure GitHub release exists | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| VERSION: ${{ needs.detect.outputs.release_version }} | |
| TARGET_SHA: ${{ needs.detect.outputs.release_sha }} | |
| run: | | |
| set -euo pipefail | |
| TAG="v${VERSION}" | |
| if gh release view "$TAG" >/dev/null 2>&1; then | |
| echo "Release $TAG already exists." | |
| else | |
| echo "Creating release: $TAG at $TARGET_SHA" | |
| gh release create "$TAG" --target "$TARGET_SHA" --title "$TAG" --generate-notes | |
| fi | |
| upload: | |
| runs-on: macos-26 | |
| needs: [detect, release] | |
| if: always() && needs.detect.outputs.build_changed == 'true' && (needs.release.result == 'success' || needs.release.result == 'skipped') | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Xcode | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: "latest-stable" | |
| - name: Prepare App Store Connect API key | |
| id: prepare | |
| env: | |
| APP_STORE_CONNECT_API_PRIVATE_KEY: ${{ secrets.APP_STORE_CONNECT_API_PRIVATE_KEY }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${APP_STORE_CONNECT_API_PRIVATE_KEY}" ]; then | |
| echo "APP_STORE_CONNECT_API_PRIVATE_KEY is not set." >&2 | |
| exit 1 | |
| fi | |
| umask 077 | |
| KEY_PATH="$RUNNER_TEMP/appstoreconnect_key.p8" | |
| printf "%s" "$APP_STORE_CONNECT_API_PRIVATE_KEY" > "$KEY_PATH" | |
| echo "APP_STORE_CONNECT_API_KEY_PATH=$KEY_PATH" >> "$GITHUB_OUTPUT" | |
| - name: Import codesign certs | |
| uses: apple-actions/import-codesign-certs@v7 | |
| with: | |
| p12-file-base64: ${{ secrets.APPSTORE_CERTIFICATES_FILE_BASE64 }} | |
| p12-password: ${{ secrets.APPSTORE_CERTIFICATES_PASSWORD }} | |
| - name: Import provisioning profiles | |
| run: misc/import_profiles.sh | |
| env: | |
| IOS_PROVISIONING_PROFILE_BASE64: ${{ secrets.IOS_PROVISIONING_PROFILE_BASE64 || '' }} | |
| - name: Verify certificates and profiles | |
| run: | | |
| set -euo pipefail | |
| echo "Current build number: ${{ needs.detect.outputs.build_number }}" | |
| echo "Available signing certificates:" | |
| security find-identity -v -p codesigning | grep "Apple Distribution" || echo "No Apple Distribution certificate found" | |
| PROFILES_DIR="$HOME/Library/MobileDevice/Provisioning Profiles" | |
| echo "" | |
| echo "Available provisioning profiles:" | |
| ls -lh "$PROFILES_DIR" 2>/dev/null | tail -n +2 || echo "No profiles found" | |
| - name: Prepare app config | |
| env: | |
| BANGUMI_APP_ID: ${{ secrets.BANGUMI_APP_ID }} | |
| BANGUMI_APP_SECRET: ${{ secrets.BANGUMI_APP_SECRET }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${BANGUMI_APP_ID}" ] || [ -z "${BANGUMI_APP_SECRET}" ]; then | |
| echo "BANGUMI_APP_ID or BANGUMI_APP_SECRET is not set." >&2 | |
| exit 1 | |
| fi | |
| cat > App/Config.xcconfig <<EOF | |
| BANGUMI_APP_ID = ${BANGUMI_APP_ID} | |
| BANGUMI_APP_SECRET = ${BANGUMI_APP_SECRET} | |
| EOF | |
| - name: Build and upload to App Store Connect | |
| env: | |
| APP_STORE_CONNECT_API_KEY_PATH: ${{ steps.prepare.outputs.APP_STORE_CONNECT_API_KEY_PATH }} | |
| APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }} | |
| APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} | |
| run: make release-ios |