Skip to content

feat(progress): extend inline progress fill to list mode and drop lin… #114

feat(progress): extend inline progress fill to list mode and drop lin…

feat(progress): extend inline progress fill to list mode and drop lin… #114

Workflow file for this run

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