ci: updated stable workflow as per workflow.py and other workflows

This commit is contained in:
mahee96
2026-02-24 22:07:36 +05:30
parent fd920be3bf
commit 21bbcd69f8
2 changed files with 97 additions and 197 deletions

View File

@@ -1,242 +1,116 @@
name: Stable SideStore build name: Stable SideStore build
on: on:
push: push:
tags: tags:
- '[0-9]+.[0-9]+.[0-9]+' # example: 1.0.0 - '[0-9]+.[0-9]+.[0-9]+'
workflow_dispatch: workflow_dispatch:
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
build: build:
name: Build SideStore - stable (on tag push) name: Build SideStore - stable
strategy: runs-on: macos-26
fail-fast: false
matrix: env:
include: RELEASE_NAME: Stable
- os: 'macos-26' CHANNEL: stable
version: '26.0' UPSTREAM_CHANNEL: ""
runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout code - uses: actions/checkout@v4
uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
fetch-depth: 0
- name: Echo Build.xcconfig - run: brew install ldid xcbeautify
- name: Setup Env
run: | run: |
echo "cat Build.xcconfig" MARKETING_VERSION=$(python3 scripts/ci/workflow.py get-marketing-version)
cat Build.xcconfig SHORT_COMMIT=$(python3 scripts/ci/workflow.py commit-id)
shell: bash
# - name: Change MARKETING_VERSION to the pushed tag that triggered this build
# run: sed -e '/MARKETING_VERSION = .*/s/= .*/= ${{ github.ref_name }}/' -i '' Build.xcconfig
- name: Echo Updated Build.xcconfig
run: |
cat Build.xcconfig
shell: bash
- name: Extract MARKETING_VERSION from Build.xcconfig
id: version
run: |
version=$(grep MARKETING_VERSION Build.xcconfig | sed -e 's/MARKETING_VERSION = //g')
echo "version=$version" >> $GITHUB_OUTPUT
echo "version=$version"
echo "MARKETING_VERSION=$version" >> $GITHUB_ENV
echo "MARKETING_VERSION=$version" >> $GITHUB_OUTPUT
echo "MARKETING_VERSION=$version"
shell: bash
- name: Fail the build if pushed tag and embedded MARKETING_VERSION in Build.xcconfig are mismatching
run: |
if [ "$MARKETING_VERSION" != "${{ github.ref_name }}" ]; then if [ "$MARKETING_VERSION" != "${{ github.ref_name }}" ]; then
echo 'Version mismatch: $tag != $marketing_version ... ' echo "Version mismatch"
echo " expected-tag : $MARKETING_VERSION" echo "Build.xcconfig: $MARKETING_VERSION"
echo " pushed-tag : ${{ github.ref_name }}" echo "Tag: ${{ github.ref_name }}"
exit 1 exit 1
fi fi
echo 'Version matches: $tag == $marketing_version ... '
echo " expected-tag : $MARKETING_VERSION"
echo " pushed-tag : ${{ github.ref_name }}"
shell: bash
- name: Install dependencies - ldid & xcbeautify echo "MARKETING_VERSION=$MARKETING_VERSION" | tee -a $GITHUB_ENV
run: | echo "SHORT_COMMIT=$SHORT_COMMIT" | tee -a $GITHUB_ENV
brew install ldid xcbeautify
- name: Setup Xcode - name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1.6.0 uses: maxim-lobanov/setup-xcode@v1.6.0
with: with:
xcode-version: ${{ matrix.version }} xcode-version: "26.0"
- name: (Build) Restore Xcode & SwiftPM Cache (Exact match) - name: Restore Cache (exact)
id: xcode-cache-restore id: xcode-cache-exact
uses: actions/cache/restore@v3 uses: actions/cache/restore@v3
with: with:
path: | path: |
~/Library/Developer/Xcode/DerivedData ~/Library/Developer/Xcode/DerivedData
~/Library/Caches/org.swift.swiftpm ~/Library/Caches/org.swift.swiftpm
key: xcode-cache-build-stable-${{ github.sha }} key: xcode-build-cache-stable-${{ github.sha }}
- name: (Build) Restore Xcode & SwiftPM Cache (Last Available) - name: Restore Cache (last)
id: xcode-cache-restore-recent if: steps.xcode-cache-exact.outputs.cache-hit != 'true'
id: xcode-cache-fallback
uses: actions/cache/restore@v3 uses: actions/cache/restore@v3
with: with:
path: | path: |
~/Library/Developer/Xcode/DerivedData ~/Library/Developer/Xcode/DerivedData
~/Library/Caches/org.swift.swiftpm ~/Library/Caches/org.swift.swiftpm
key: xcode-cache-build-stable- key: xcode-build-cache-stable-
- name: (Build) Clean previous build artifacts - name: Clean
run: python3 scripts/ci/workflow.py clean
- name: Build
id: build
env:
BUILD_LOG_ZIP_PASSWORD: ${{ secrets.BUILD_LOG_ZIP_PASSWORD }}
run: | run: |
make clean python3 scripts/ci/workflow.py build; STATUS=$?
mkdir -p build/logs python3 scripts/ci/workflow.py encrypt-build
shell: bash exit $STATUS
- name: (Build) List Files and derived data - name: Save Cache
if: always() if: ${{ steps.xcode-cache-fallback.outputs.cache-hit != 'true' }}
shell: bash
run: |
echo ">>>>>>>>> Workdir <<<<<<<<<<"
ls -la .
echo ""
echo ">>>>>>>>> SideStore <<<<<<<<<<"
find SideStore -maxdepth 2 -exec ls -ld {} + || true # List contents if directory exists
echo ""
echo ">>>>>>>>> Dependencies <<<<<<<<<<"
find Dependencies -maxdepth 2 -exec ls -ld {} + || true # List contents if directory exists
echo ""
echo ">>>>>>>>> Xcode-Derived-Data <<<<<<<<<<"
ls -la ~/Library/Developer/Xcode/DerivedData || true # List contents if directory exists
echo ""
- name: Build SideStore.xcarchive
# using 'tee' to intercept stdout and log for detailed build-log
run: |
NSUnbufferedIO=YES make -B build 2>&1 | tee -a build/logs/build.log | xcbeautify --renderer github-actions && exit ${PIPESTATUS[0]}
shell: bash
- name: Fakesign app
run: make fakesign | tee -a build/logs/build.log
shell: bash
- name: Convert to IPA
run: make ipa | tee -a build/logs/build.log
shell: bash
- name: (Build) Save Xcode & SwiftPM Cache
id: cache-save
if: ${{ steps.xcode-cache-restore.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v3 uses: actions/cache/save@v3
with: with:
path: | path: |
~/Library/Developer/Xcode/DerivedData ~/Library/Developer/Xcode/DerivedData
~/Library/Caches/org.swift.swiftpm ~/Library/Caches/org.swift.swiftpm
key: xcode-cache-build-stable-${{ github.sha }} key: xcode-build-cache-stable-${{ github.sha }}
- name: (Build) List Files and Build artifacts
run: |
echo ">>>>>>>>> Workdir <<<<<<<<<<"
ls -la .
echo ""
echo ">>>>>>>>> Build <<<<<<<<<<" - uses: actions/upload-artifact@v4
find build -maxdepth 3 -exec ls -ld {} + || true # List contents if directory exists
echo ""
echo ">>>>>>>>> SideStore <<<<<<<<<<"
find SideStore -maxdepth 3 -exec ls -ld {} + || true # List contents if directory exists
echo ""
echo ">>>>>>>>> SideStore.xcarchive <<<<<<<<<<"
find SideStore.xcarchive -maxdepth 3 -exec ls -ld {} + || true # List contents if directory exists
echo ""
echo ">>>>>>>>> Xcode-Derived-Data <<<<<<<<<<"
ls -la ~/Library/Developer/Xcode/DerivedData || true # List contents if directory exists
echo ""
shell: bash
- name: Encrypt build-logs for upload
id: encrypt-build-log
run: |
DEFAULT_BUILD_LOG_PASSWORD=12345
BUILD_LOG_ZIP_PASSWORD=${{ secrets.BUILD_LOG_ZIP_PASSWORD }}
BUILD_LOG_ZIP_PASSWORD=${BUILD_LOG_ZIP_PASSWORD:-$DEFAULT_BUILD_LOG_PASSWORD}
if [ "$BUILD_LOG_ZIP_PASSWORD" == "$DEFAULT_BUILD_LOG_PASSWORD" ]; then
echo "Warning: BUILD_LOG_ZIP_PASSWORD is not set. Defaulting to '${DEFAULT_BUILD_LOG_PASSWORD}'."
fi
pushd build/logs && zip -e -P "$BUILD_LOG_ZIP_PASSWORD" ../../encrypted-build-logs.zip * || popd
echo "::set-output name=encrypted::true"
shell: bash
- name: Upload encrypted-build-logs.zip
id: attach-encrypted-build-log
if: ${{ always() && steps.encrypt-build-log.outputs.encrypted == 'true' }}
uses: actions/upload-artifact@v4
with: with:
name: encrypted-build-logs-${{ steps.version.outputs.version }}.zip name: encrypted-build-logs-${{ env.MARKETING_VERSION }}.zip
path: encrypted-build-logs.zip path: encrypted-build-logs.zip
- name: Upload SideStore.ipa Artifact - uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v4
with: with:
name: SideStore-${{ steps.version.outputs.version }}.ipa name: SideStore-${{ env.MARKETING_VERSION }}.ipa
path: SideStore.ipa path: SideStore.ipa
- name: Zip dSYMs - uses: actions/upload-artifact@v4
run: zip -r -9 ./SideStore.dSYMs.zip ./SideStore.xcarchive/dSYMs
shell: bash
- name: Upload *.dSYM Artifact
uses: actions/upload-artifact@v4
with: with:
name: SideStore-${{ steps.version.outputs.version }}-dSYMs.zip name: SideStore-${{ env.MARKETING_VERSION }}-dSYMs.zip
path: SideStore.dSYMs.zip path: SideStore.dSYMs.zip
- name: Get current date
id: date
run: echo "date=$(date -u +'%c')" >> $GITHUB_OUTPUT
shell: bash
- name: Get current date in AltStore date form
id: date_altstore
run: echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT
shell: bash
- name: Upload to releases - name: Upload to releases
uses: IsaacShelton/update-existing-release@v1.3.1 env:
with: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }} run: |
draft: true python3 scripts/ci/workflow.py upload-release \
release: ${{ github.ref_name }} # name "$RELEASE_NAME" \
tag: ${{ github.ref_name }} "${{ github.ref_name }}" \
# stick with what the user pushed, do not use latest commit or anything, "$GITHUB_SHA" \
# ex: if we want to go back to previous release due to hot issue, dev can create a new tag pointing to that older working tag/commit so as to keep it as an update (to revert major issue) "$GITHUB_REPOSITORY" \
# in this case we do not want the tag to be auto-updated to latest "$UPSTREAM_CHANNEL" \
updateTag: false "true"
prerelease: false
files: >
SideStore.ipa
SideStore.dSYMs.zip
encrypted-build-logs.zip
body: |
<!-- NOTE: to reset SideSource cache, go to `https://apps.sidestore.io/reset-cache/nightly/<sidesource key>`. This is not included in the GitHub Action since it makes draft releases so they can be edited and have a changelog. -->
## Changelog
- TODO
## Build Info
Built at (UTC): `${{ steps.date.outputs.date }}`
Built at (UTC date): `${{ steps.date_altstore.outputs.date }}`
Commit SHA: `${{ github.sha }}`
Version: `${{ steps.version.outputs.version }}`

View File

@@ -396,7 +396,18 @@ def last_successful_commit(workflow, branch):
return None return None
def upload_release(release_name, release_tag, commit_sha, repo, upstream_tag_recommended): def upload_release(release_name, release_tag, commit_sha, repo, upstream_tag_recommended, is_stable=False):
is_stable = str(is_stable).lower() in ("1", "true", "yes")
if is_stable:
draft = True # always create a draft for stable and let user publish release
update_tag = False
prerelease = False
else:
draft = False
update_tag = True # update existing
prerelease = True
token = getenv("GH_TOKEN") token = getenv("GH_TOKEN")
if token: if token:
os.environ["GH_TOKEN"] = token os.environ["GH_TOKEN"] = token
@@ -423,7 +434,7 @@ def upload_release(release_name, release_tag, commit_sha, repo, upstream_tag_rec
f"--retrieve {release_tag} " f"--retrieve {release_tag} "
f"--output-dir {ROOT}" f"--output-dir {ROOT}"
) )
# normalize section header
release_notes = re.sub( release_notes = re.sub(
r'^\s*#{1,6}\s*what(?:\'?s|\s+is)?\s+(?:new|changed).*', r'^\s*#{1,6}\s*what(?:\'?s|\s+is)?\s+(?:new|changed).*',
"## What's Changed", "## What's Changed",
@@ -440,19 +451,27 @@ def upload_release(release_name, release_tag, commit_sha, repo, upstream_tag_rec
f"(https://github.com/{repo}/releases?q={tag}).\n\n" f"(https://github.com/{repo}/releases?q={tag}).\n\n"
) )
header = getFormattedUploadMsg(release_name, release_tag, commit_sha, repo, upstream_block, built_time, built_date, marketing_version) header = getFormattedUploadMsg(
body = header + "\n\n" + release_notes.lstrip() + "\n" release_name, commit_sha, repo, upstream_block,
built_time, built_date, marketing_version, is_stable,
)
body = header + release_notes.lstrip() + "\n"
body_file = ROOT / "release_body.md" body_file = ROOT / "release_body.md"
body_file.write_text(body, encoding="utf-8") body_file.write_text(body, encoding="utf-8")
prerelease_flag = "--prerelease" if is_beta else "" prerelease_flag = "--prerelease" if is_beta else ""
draft_flag = "--draft" if draft else ""
prerelease_flag = "--prerelease" if prerelease else ""
latest_flag = "" if update_tag else "--latest=false"
run( run(
f'gh release edit "{release_tag}" ' f'gh release edit "{release_tag}" '
f'--title "{release_name}" ' f'--title "{release_name}" '
f'--notes-file "{body_file}" ' f'--notes-file "{body_file}" '
f'{prerelease_flag}' f'{draft_flag} {prerelease_flag} {latest_flag}'
) )
run( run(
@@ -461,19 +480,26 @@ def upload_release(release_name, release_tag, commit_sha, repo, upstream_tag_rec
f'--clobber' f'--clobber'
) )
def getFormattedUploadMsg(release_name, release_tag, commit_sha, repo, upstream_block, built_time, built_date, marketing_version):
return f""" def getFormattedUploadMsg(release_name, commit_sha, repo, upstream_block, built_time, built_date, marketing_version, is_stable):
experimental_header = ""
if not is_stable:
experimental_header = f"""
This is an ⚠️ **EXPERIMENTAL** ⚠️ {release_name} build for commit [{commit_sha}](https://github.com/{repo}/commit/{commit_sha}). This is an ⚠️ **EXPERIMENTAL** ⚠️ {release_name} build for commit [{commit_sha}](https://github.com/{repo}/commit/{commit_sha}).
{release_name} builds are **extremely experimental builds only meant to be used by developers and beta testers. They often contain bugs and experimental features. Use at your own risk!** {release_name} builds are **extremely experimental builds only meant to be used by developers and beta testers. They often contain bugs and experimental features. Use at your own risk!**
{upstream_block}## Build Info """.lstrip("\n")
header = f"""
{experimental_header}{upstream_block}## Build Info
Built at (UTC): `{built_time}` Built at (UTC): `{built_time}`
Built at (UTC date): `{built_date}` Built at (UTC date): `{built_date}`
Commit SHA: `{commit_sha}` Commit SHA: `{commit_sha}`
Version: `{marketing_version}` Version: `{marketing_version}`
""".lstrip("\n") """.lstrip("\n")
return header
# ---------------------------------------------------------- # ----------------------------------------------------------
# ENTRYPOINT # ENTRYPOINT
@@ -534,7 +560,7 @@ COMMANDS = {
"retrieve-release-notes" : (retrieve_release_notes, 1, "<tag>"), "retrieve-release-notes" : (retrieve_release_notes, 1, "<tag>"),
"deploy" : (deploy, 9, "deploy" : (deploy, 9,
"<repo> <source_json> <release_tag> <short_commit> <marketing_version> <channel> <bundle_id> <ipa_name> [last_successful_commit]"), "<repo> <source_json> <release_tag> <short_commit> <marketing_version> <channel> <bundle_id> <ipa_name> [last_successful_commit]"),
"upload-release" : (upload_release, 5, "<release_name> <release_tag> <commit_sha> <repo> <upstream_tag_recommended>"), "upload-release" : (upload_release, 5, "<release_name> <release_tag> <commit_sha> <repo> <upstream_tag_recommended> [is_stable]"),
} }
def main(): def main():