Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
8cb2901
ci: publish AltKeeper Docker image for Raspberry Pi arm64
pingpingjinping Oct 24, 2026
f103611
Merge latest AltKeeper upstream (2026-10-25)
pingpingjinping Oct 24, 2026
f712a14
feat: query installed user apps through installation_proxy
pingpingjinping Oct 24, 2026
151cc09
feat: filter unattended renewals by installed apps and share verified…
pingpingjinping Oct 24, 2026
491b05c
feat(web): per-app renew and safe team-scoped profile deletion with b…
pingpingjinping Oct 24, 2026
14f2a6c
feat: fall back to all profile renewals when installed-app lookup fails
pingpingjinping Oct 24, 2026
773b5c7
feat(web): individual renewal and confirmation-backed profile deletio…
pingpingjinping Oct 24, 2026
3ae1a63
ci: skip duplicate PR image build; publish arm64 only on main or tag
pingpingjinping Oct 24, 2026
71f0115
docs: explain installed-only renewals, fallback, per-app control and …
pingpingjinping Oct 24, 2026
ebb42d2
Merge AltKeeper per-app renewal and profile controls
pingpingjinping Oct 24, 2026
d40444e
feat: safely prune expired profile backups on a persisted 30-day cadence
pingpingjinping Oct 24, 2026
949f748
feat: run monthly backup cleanup in persistent AltKeeper web service
pingpingjinping Oct 25, 2026
1f134fe
docs: describe safe 30-day profile backup cleanup and retention
pingpingjinping Oct 25, 2026
22458fe
Merge monthly cleanup of expired provisioning profile backups
pingpingjinping Oct 25, 2026
1e8e823
feat(web): persistent auto renewal ON/OFF and daily KST scheduler
pingpingjinping Oct 25, 2026
5e749ad
fix: avoid cross-lock deadlock between automatic job and web state
pingpingjinping Oct 25, 2026
4081e96
feat(web ui): enable/disable and set local-time auto-renew schedule
pingpingjinping Oct 25, 2026
de59d03
docs: built-in KST web auto-renew schedule and no additional systemd …
pingpingjinping Oct 25, 2026
d9aa2cf
chore: set default automatic renewal schedule to 06:00 KST
pingpingjinping Oct 25, 2026
e212506
chore: set default automatic renewal schedule to 06:00 KST
pingpingjinping Oct 25, 2026
9684b23
chore: set default automatic renewal schedule to 06:00 KST
pingpingjinping Oct 25, 2026
860bbb6
Merge built-in auto-renew scheduler with web controls
pingpingjinping Oct 25, 2026
918de34
feat: identify host/extension profile groups with exact team marker
pingpingjinping Oct 25, 2026
c863f9b
fix: renew host and extensions as one app, including installed-only a…
pingpingjinping Oct 25, 2026
1650d3e
feat(web): group app and extension profiles, show earliest member expiry
pingpingjinping Oct 25, 2026
8b8f709
feat: persisted half-hour retry schedule and protected Discord failur…
pingpingjinping Oct 25, 2026
e5784b9
feat: configurable 1–6 day threshold, 30m retry twice and per-group o…
pingpingjinping Oct 25, 2026
219c826
feat: secured Discord webhook settings and web backup restore
pingpingjinping Oct 25, 2026
755e401
feat(ui): expandable grouped apps, renew preview, profile restore, re…
pingpingjinping Oct 25, 2026
40b3d37
fix: borrow latest profiles while grouping extension bundles
pingpingjinping Oct 25, 2026
a416552
fix: borrow latest profiles while grouping extension bundles
pingpingjinping Oct 25, 2026
3c75baa
build: install curl for Discord notifications
pingpingjinping Oct 25, 2026
6dbddb5
docs: grouped renewal, adjustable threshold, 30-minute retries and Di…
pingpingjinping Oct 25, 2026
499fb14
Merge pull request #5 from pingpingjinping/feature/grouped-app-renew-…
pingpingjinping Oct 25, 2026
52b2ef1
fix: group extensions using embedded signing Team IDs, not only activ…
pingpingjinping Oct 25, 2026
13795e2
test(web): assert real iOS bundle names display as 2 apps and 6 membe…
pingpingjinping Oct 25, 2026
34e3941
Merge pull request #6 from pingpingjinping/fix/extension-bundle-group…
pingpingjinping Oct 25, 2026
6ddd862
fix: strip profile Team ID suffix only for host/extension comparisons…
pingpingjinping Oct 25, 2026
6613095
test: use genuinely unrelated bundle name for negative grouping case
pingpingjinping Oct 25, 2026
3fb47e7
fix: installed-only renewal recognizes raw and normalized host app IDs
pingpingjinping Oct 25, 2026
5c1e5f6
test(web): regress using raw phone provisioning IDs with trailing sig…
pingpingjinping Oct 25, 2026
49b6753
Merge pull request #7 from pingpingjinping/fix/profile-suffix-aware-a…
pingpingjinping Oct 25, 2026
ffc0ac0
feat(web): add Apple touch and Safari bookmark PNG icon assets
pingpingjinping Oct 25, 2026
e1ee4d1
feat(web): serve public Safari bookmark PNGs and safe Discord webhook…
pingpingjinping Oct 25, 2026
5287bc1
feat(web): link Safari touch icon and add Discord send-test button
pingpingjinping Oct 25, 2026
6ca0623
fix(web): use explicit Axum body for icon bytes
pingpingjinping Oct 25, 2026
4331816
docs: propose Korean UI translations for review only; do not change l…
pingpingjinping Oct 25, 2026
9379564
test: correct Rust PNG signature byte-string escapes
pingpingjinping Oct 25, 2026
e7e8f0b
feat(web): add reviewed Korean localization, language switch, respons…
pingpingjinping Oct 25, 2026
62f2a27
feat(i18n): add reviewed Korean terms for all dynamic UI messages
pingpingjinping Oct 25, 2026
32735c5
feat(web): localize dynamic app statuses, progress messages and confi…
pingpingjinping Oct 25, 2026
df2dde3
style(web): enforce equal-width centered action buttons across respon…
pingpingjinping Oct 25, 2026
7aecef3
docs: mark Korean UI review approved and record language toggle and l…
pingpingjinping Oct 25, 2026
916ff73
test(web): syntax-check embedded JavaScript and verify localized layo…
pingpingjinping Oct 25, 2026
439b13f
ci: check localized HTML script syntax and equal-sized action control…
pingpingjinping Oct 25, 2026
a537fea
style(web): use consistent 184px action buttons for install, login an…
pingpingjinping Oct 25, 2026
3956608
Merge pull request #8 from pingpingjinping/feature/safari-favicon-dis…
pingpingjinping Oct 25, 2026
74f056d
feat(signer): inspect IPA extension manifests and exclude unselected …
pingpingjinping Oct 25, 2026
8d6f807
fix(signer): retain selected extensions through Bundle public method
pingpingjinping Oct 25, 2026
3f8fb5e
feat(bundle): maintain in-memory extension tree after selection
pingpingjinping Oct 25, 2026
0e8703f
feat(signer): filter unselected extensions before App ID registration
pingpingjinping Oct 25, 2026
51d8a82
feat(signing): pass extension selection into signing pipeline
pingpingjinping Oct 25, 2026
e746031
feat(web): preflight IPA extension selection and confirm before signing
pingpingjinping Oct 25, 2026
02c6e38
feat(web-ui): show checked-by-default Extension selection only for co…
pingpingjinping Oct 25, 2026
46722db
test(web): validate IPA extension selection UI and endpoint wiring
pingpingjinping Oct 25, 2026
204d7ab
fix(web): expire staged IPAs and clean up abandoned uploads on startup
pingpingjinping Oct 25, 2026
a349a6a
fix(ipa-inspect): avoid keeping borrowed ZIP entry name across read
pingpingjinping Oct 25, 2026
0da9e8c
fix(signer): rebuild bundle tree after extension pruning to omit remo…
pingpingjinping Oct 25, 2026
23a06a1
refactor: avoid redundant bundle extension state mutation
pingpingjinping Oct 25, 2026
2e39529
feat(ipa): inspect main app identity and support optional name/Bundle…
pingpingjinping Oct 25, 2026
dbe3036
feat(signer): apply independent name/Bundle ID options before registr…
pingpingjinping Oct 25, 2026
2447dd0
feat(apple): forward optional new-install identity overrides to signer
pingpingjinping Oct 25, 2026
ac7d2e9
feat(web): customize only new installs and block existing Bundle ID c…
pingpingjinping Oct 25, 2026
f1e7cc4
feat(ui): independent app-name and Bundle ID inputs only for new IPA …
pingpingjinping Oct 25, 2026
eadf48f
test(ui): cover new-install identity inputs and updated IPA inspectio…
pingpingjinping Oct 25, 2026
7a674e0
fix(app-name): update localized InfoPlist.strings so renamed apps dis…
pingpingjinping Oct 25, 2026
1fa26a3
test(web): verify independent new-install rename and clone Bundle ID …
pingpingjinping Oct 25, 2026
83c6d47
fix(rust): preserve UTF-16 byte array lifetime when renaming localize…
pingpingjinping Oct 25, 2026
f8a7c57
fix(build): enable Axum query extractor for IPA customization preflight
pingpingjinping Oct 25, 2026
961cd9d
fix(build): avoid new Axum query dependency and lockfile changes
pingpingjinping Oct 25, 2026
7b747f9
fix(web): parse simple customization flag from request URI without qu…
pingpingjinping Oct 25, 2026
d0c6a1d
test(safety): block name/Bundle ID overrides for both installed ID fo…
pingpingjinping Oct 25, 2026
39591a3
Merge pull request #9 from pingpingjinping/feature/ipa-extension-sele…
pingpingjinping Oct 25, 2026
0860bc1
Merge pull request #10 from pingpingjinping/feature/ipa-new-install-i…
pingpingjinping Oct 25, 2026
691d587
fix(ui): preserve responsive button alignment on latest IPA install UI
pingpingjinping Oct 25, 2026
36e4cbf
test(ui): preserve new-install controls and validate compact 3-button…
pingpingjinping Oct 25, 2026
bfde9ca
Merge pull request #11 from pingpingjinping/fix/dashboard-button-row-…
pingpingjinping Oct 25, 2026
582e9de
fix: prevent scheduler deadlock and fail incomplete renewals
pingpingjinping Oct 25, 2026
dbc8d59
fix(web): preserve auto-renew drafts and serialize status polling
pingpingjinping Oct 25, 2026
5a14216
fix(web): retain saved draft until status confirms settings
pingpingjinping Oct 25, 2026
d463ed7
test(web): accept Windows CRLF in embedded script checks
pingpingjinping Oct 25, 2026
2081be3
Merge pull request #12 from pingpingjinping/fix/renewal-deadlock-and-…
pingpingjinping Oct 25, 2026
46d3cda
Merge pull request #13 from pingpingjinping/fix/web-draft-and-polling…
pingpingjinping Oct 25, 2026
9c2014a
fix: show IPA progress in install card and retain signing error causes
pingpingjinping Oct 25, 2026
d8661fb
Merge pull request #14 from pingpingjinping/fix/ipa-progress-and-sign…
pingpingjinping Oct 25, 2026
5e2d0a8
ci: build amd64 and arm64 natively in parallel and assemble manifest
pingpingjinping Oct 25, 2026
ede8d0a
Merge pull request #15 from pingpingjinping/perf/native-arm64-paralle…
pingpingjinping Oct 25, 2026
c61e687
perf(install): package signed IPA for fast Wi-Fi staging
pingpingjinping Oct 25, 2026
b6a9f3a
perf(install): stage one signed IPA over Wi-Fi instead of thousands o…
pingpingjinping Oct 25, 2026
4edd703
perf(install): stage one signed IPA over Wi-Fi instead of thousands o…
pingpingjinping Oct 25, 2026
72c4b2e
perf(install): stage one signed IPA over Wi-Fi instead of thousands o…
pingpingjinping Oct 25, 2026
9c8d337
perf(install): stage one signed IPA over Wi-Fi instead of thousands o…
pingpingjinping Oct 25, 2026
3e4c7d0
perf(install): stage one signed IPA over Wi-Fi instead of thousands o…
pingpingjinping Oct 25, 2026
5dddc36
perf(install): stage one signed IPA over Wi-Fi instead of thousands o…
pingpingjinping Oct 25, 2026
3286787
fix(install): import idevice stream write trait for AFC upload
pingpingjinping Oct 25, 2026
250ce9c
fix(install): stage IPA correctly and pass signed CFBundleIdentifier
pingpingjinping Oct 25, 2026
3c5f5a7
fix(install): clean up staged IPA after the install completes
pingpingjinping Oct 25, 2026
b4f37ca
Merge pull request #16 from pingpingjinping/perf/ipa-archive-wifi-upl…
pingpingjinping Oct 25, 2026
d653394
feat(web): play tiny muted video only during IPA install
pingpingjinping Oct 25, 2026
e80b7ac
test(web): verify install-only keepawake lifecycle
pingpingjinping Oct 25, 2026
a89dcfe
fix(web): embed verified 968-byte H264 keepawake clip
pingpingjinping Oct 25, 2026
60674c9
fix(test): pass a newline when evaluating keepawake helper
pingpingjinping Oct 25, 2026
62c0032
feat(web): add standalone five-minute screen-on video test without an…
pingpingjinping Oct 25, 2026
6563d16
test(web): cover standalone five-minute keepawake test and install-on…
pingpingjinping Oct 25, 2026
950dee0
fix(web): prevent the hidden video from autoplaying outside installs …
pingpingjinping Oct 25, 2026
5e00bef
Merge pull request #17 from pingpingjinping/feat/install-only-silent-…
pingpingjinping Oct 25, 2026
1f26140
fix(web): permit embedded H264 video under strict CSP
pingpingjinping Oct 25, 2026
5bd4dd2
style(web): ensure keepawake video has a visible black fallback
pingpingjinping Oct 25, 2026
d714cac
test(web): guard against blocking embedded video in CSP
pingpingjinping Oct 25, 2026
a1951bf
Merge pull request #18 from pingpingjinping/fix/allow-embedded-keepaw…
pingpingjinping Oct 25, 2026
db8553d
revert(web): remove ineffective video overlay and manual screen-on test
pingpingjinping Oct 25, 2026
61aacab
revert(test): remove video-only UI assertions
pingpingjinping Oct 25, 2026
21226eb
revert(web): restore strict media-blocking CSP
pingpingjinping Oct 25, 2026
cf62a7f
Merge pull request #19 from pingpingjinping/revert/remove-failed-vide…
pingpingjinping Oct 25, 2026
6509424
feat(https): add isolated private LAN Caddy setup and certificate guide
pingpingjinping Oct 25, 2026
84f34f4
feat(https): add isolated private LAN Caddy setup and certificate guide
pingpingjinping Oct 25, 2026
198053e
feat(https): add isolated private LAN Caddy setup and certificate guide
pingpingjinping Oct 25, 2026
8c2c3ab
feat(web): use HTTPS Screen Wake Lock during IPA installs with a comp…
pingpingjinping Oct 25, 2026
7d0411d
test(web): cover HTTPS proxy constraints and Screen Wake Lock lifecycle
pingpingjinping Oct 25, 2026
b55388a
fix(web): distinguish insecure HTTP from unsupported Wake Lock
pingpingjinping Oct 25, 2026
aa2f51e
docs(https): explain that HTTPS home-screen mode requires a new shortcut
pingpingjinping Oct 25, 2026
404f595
Merge pull request #20 from pingpingjinping/feat/altkeeper-lan-https-…
pingpingjinping Oct 25, 2026
ef5bd92
revert: restore the post-PR19 dashboard without experimental Wake Lock
pingpingjinping Oct 25, 2026
c6fb38b
revert: restore the post-PR19 dashboard without experimental Wake Lock
pingpingjinping Oct 25, 2026
01df432
revert: remove unused experimental local HTTPS proxy example
pingpingjinping Oct 25, 2026
6440025
revert: remove unused experimental local HTTPS proxy example
pingpingjinping Oct 25, 2026
c6cea34
revert: remove unused experimental local HTTPS proxy example
pingpingjinping Oct 25, 2026
f11b806
Merge pull request #22 from pingpingjinping/revert/remove-lan-https-w…
pingpingjinping Oct 25, 2026
f4a78ca
Merge pull request #15 from pingpingjinping/main
BartolomeoRusso9 Oct 25, 2026
0fb3aec
Korean to English
BartolomeoRusso9 Oct 25, 2026
5992380
Fix
BartolomeoRusso9 Oct 25, 2026
7a6c000
Fix
BartolomeoRusso9 Oct 25, 2026
d3480f7
Update Cargo.lock
BartolomeoRusso9 Oct 25, 2026
55b8296
Fix
BartolomeoRusso9 Oct 25, 2026
58fb793
Fix update staging, restart log polling, backup cleanup, localized fi…
coderabbitai[bot] Oct 25, 2026
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
126 changes: 104 additions & 22 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Prova il codice e pubblica l'immagine Docker su GitHub Container Registry (ghcr.io).
#
# - Pull request: prova i test e la compilazione dell'immagine (amd64), senza pubblicare.
# - Push su main: pubblica `latest` e `sha-<commit>` (solo amd64: è la compilazione veloce).
# - Pull request: esegue i test Linux e Windows e compila il Dockerfile per amd64, senza pubblicare immagini.
# - Push su main: pubblica `latest` e `sha-<commit>` per amd64 e arm64.
# - Tag `vX.Y.Z` (per esempio `git tag v0.2.0 && git push --tags`): pubblica `X.Y.Z`, `X.Y` e
# `latest`, per amd64 e arm64 (l'arm64 gira sotto emulazione: richiede parecchi minuti).
# `latest`, per amd64 e arm64 (build nativi paralleli, senza QEMU).
#
# L'immagine: ghcr.io/<utente>/altkeeper. Se il repo è privato lo è anche il pacchetto: per
# usarlo da un server serve `docker login ghcr.io` con un token che possa leggere i pacchetti,
Expand All @@ -28,6 +28,8 @@ jobs:
contents: read
steps:
- uses: actions/checkout@v7
- name: Check localized web UI
run: node scripts/check-web-ui.cjs
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test --locked
Expand All @@ -44,6 +46,8 @@ jobs:
contents: read
steps:
- uses: actions/checkout@v7
- name: Check localized web UI
run: node scripts/check-web-ui.cjs
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test --locked
Expand All @@ -60,43 +64,121 @@ jobs:
$output = cargo run --locked -- --help
if ($LASTEXITCODE -ne 0 -or -not ($output -match '^uso: altkeeper')) { throw "Italian CLI help failed: $output" }

image:
needs: test
build-pr:
if: github.event_name == 'pull_request'
needs: [test, test-windows]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v7

- uses: docker/setup-qemu-action@v4
- uses: docker/setup-buildx-action@v4
- uses: docker/build-push-action@v7
with:
context: .
platforms: linux/amd64
push: false
cache-from: type=gha,scope=altkeeper-amd64

# Il login serve solo per pubblicare: le pull request non hanno il permesso di scrivere.
image:
# Build architectures concurrently on native runners for publishing.
if: github.event_name != 'pull_request'
needs: [test, test-windows]
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-latest
- arch: arm64
platform: linux/arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v7
# No QEMU: Rust is compiled natively for each target.
- uses: docker/setup-buildx-action@v4
- uses: docker/login-action@v4
if: github.event_name != 'pull_request'
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: image-name
run: echo "image=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
- id: meta
uses: docker/metadata-action@v6
with:
images: ${{ steps.image-name.outputs.image }}
- id: build
uses: docker/build-push-action@v7
with:
context: .
platforms: ${{ matrix.platform }}
# Immutable per-arch pushes; only the final manifest receives tags.
outputs: type=image,name=${{ steps.image-name.outputs.image }},push-by-digest=true,name-canonical=true,push=true
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=altkeeper-${{ matrix.arch }}
cache-to: type=gha,scope=altkeeper-${{ matrix.arch }},mode=max
- name: Export image digest
run: |
mkdir -p "${RUNNER_TEMP}/digests"
digest="${{ steps.build.outputs.digest }}"
test -n "${digest}"
touch "${RUNNER_TEMP}/digests/${digest#sha256:}"
- uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.arch }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1

image-manifest:
# Publish tags only after both architecture builds succeed.
if: github.event_name != 'pull_request'
needs: [image]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
merge-multiple: true
- uses: docker/setup-buildx-action@v4
- uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: image-name
run: echo "image=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
- id: meta
uses: docker/metadata-action@v6
with:
images: ghcr.io/${{ github.repository }}
images: ${{ steps.image-name.outputs.image }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }}
type=sha

- uses: docker/build-push-action@v7
with:
context: .
# I tag di versione pubblicano anche arm64; il resto solo amd64 (più rapido).
platforms: ${{ startsWith(github.ref, 'refs/tags/v') && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Create multi-platform manifest
working-directory: ${{ runner.temp }}/digests
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
run: |
# Never publish a partial multi-architecture manifest.
test "$(find . -maxdepth 1 -type f | wc -l)" -eq 2
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ steps.image-name.outputs.image }}@sha256:%s ' *)
- name: Inspect published manifest
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
run: |
docker buildx imagetools inspect "$(jq -r '.tags[0]' <<< "$DOCKER_METADATA_OUTPUT_JSON")"
105 changes: 105 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Compila AltKeeper per Windows, Linux e macOS e pubblica tutto in una GitHub Release.
#
# - Windows: `altkeeper.exe` + `altkeeper.exe.sha256`. L'aggiornamento dall'icona nella barra di
# sistema scarica proprio questi due file: i nomi non vanno cambiati.
# - Linux (x86-64 e arm64) e macOS (Apple Silicon e Intel): `altkeeper-<tag>-<sistema>-<arch>.tar.gz`
# con il suo `.sha256`. Sono download manuali: l'auto-aggiornamento è solo per Windows.
#
# Si lancia con un tag, per esempio: git tag v0.3.1 && git push origin v0.3.1
# Il numero del tag deve coincidere con `version` in Cargo.toml.
name: release

on:
push:
tags: ["v*"]

jobs:
build:
strategy:
fail-fast: true
matrix:
include:
- name: windows
runner: windows-latest
test: true
# ubuntu-22.04: glibc 2.35, così il binario gira anche su distribuzioni non recentissime.
- name: linux-x86_64
runner: ubuntu-22.04
test: true
- name: linux-aarch64
runner: ubuntu-22.04-arm
test: true
- name: macos-aarch64
runner: macos-latest
test: false
- name: macos-x86_64
runner: macos-15-intel
test: false
runs-on: ${{ matrix.runner }}
permissions:
contents: read
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2
- name: Check that the tag matches Cargo.toml
run: |
version=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1)
if [ "v$version" != "${GITHUB_REF_NAME}" ]; then
echo "tag ${GITHUB_REF_NAME} != Cargo.toml v$version"; exit 1
fi
- name: Test
if: matrix.test
run: cargo test --locked
- run: cargo build --release --locked
- name: Package (Windows)
if: matrix.name == 'windows'
run: |
mkdir dist
cp target/release/altkeeper.exe dist/altkeeper.exe
cd dist
hash=$(sha256sum altkeeper.exe | cut -d' ' -f1)
printf '%s altkeeper.exe' "$hash" > altkeeper.exe.sha256
- name: Package (Linux, macOS)
if: matrix.name != 'windows'
run: |
pkg="altkeeper-${GITHUB_REF_NAME}-${{ matrix.name }}"
mkdir -p "dist/$pkg"
cp target/release/altkeeper LICENSE README.md README.it.md "dist/$pkg/"
cp -r examples "dist/$pkg/examples"
cd dist
tar -czf "$pkg.tar.gz" "$pkg"
rm -rf "$pkg"
if command -v sha256sum >/dev/null; then
sha256sum "$pkg.tar.gz" > "$pkg.tar.gz.sha256"
else
shasum -a 256 "$pkg.tar.gz" > "$pkg.tar.gz.sha256"
fi
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: dist-${{ matrix.name }}
path: dist/*
if-no-files-found: error
retention-days: 1

publish:
# Una sola release, creata solo se tutte le build sono riuscite.
needs: [build]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
path: dist
pattern: dist-*
merge-multiple: true
- name: List files
run: ls -l dist
- uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
with:
files: dist/*
fail_on_unmatched_files: true
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ notify.conf
renew.log
.ultimo-errore
/profili-salvati/
altkeeper.log
altkeeper.log.1
altkeeper.new.exe
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Changelog

## Unreleased
## 0.3.0

### Fixed
- **USB on Windows without configuration.** When `USBMUXD_SOCKET_ADDRESS` is not set, Windows now
uses the usbmuxd of iTunes / Apple Devices on `127.0.0.1:27015` instead of failing to find the
phone. Ported from the USB-fix branch.
- **Install hung forever over USB on iOS 27.** On USB, installing an IPA now goes through AFC + installation_proxy via usbmuxd (same path as `pymobiledevice3 apps install`) instead of the CoreDeviceProxy software tunnel, and the profile client prefers the lockdown service too. App install and profile install now have timeouts, so a stuck phone produces an error instead of a silent hang. The status line says "over USB" or "over Wi-Fi" according to the real transport. Not compiled in this environment: please run `cargo build` and test.

### Changed
Expand All @@ -17,6 +20,20 @@
unattended renewals (profiles + App IDs) work again.

### Added
- **Windows tray icon (`altkeeper tray`, also what a double-click on `altkeeper.exe` starts).**
AltServer and the web page run without a terminal, with an icon next to the clock (AltKeeper
logo, grey while the iPhone is unreachable), a menu (*Open AltKeeper*, *Show logs*, *Start with
Windows*, *Check for updates*, *Quit*), a window with the web page (WebView2) and toast
notifications for renewed profiles, installed apps and failures. Ported from AltKeeperPlus.
- **Updates from the tray and `release.yml`.** The icon checks the fork's GitHub releases once a
day; *Update now* verifies the SHA-256, restarts and rolls back if the new version does not
start. `release.yml` builds `altkeeper.exe` for Windows on a `v*` tag. Ported from AltKeeperPlus.
- **Persistent logs.** Server lines (AltServer, web page, DNS-SD) carry a timestamp and are
also written to `altkeeper.log` (rotated at 5 MB) and shown in a new **Logs** section of the
web page (`/api/logs`). Ported from AltKeeperPlus.
- **AltKeeper logo as the icon of `altkeeper.exe`** (embedded by the new `build.rs` on Windows builds, from `assets/altkeeper.ico`), besides the tray and window icons.
- **App / App ID counters** next to "Your apps" in the web page (3 active apps and 10 App IDs for
a free account; an estimate from the profiles on the phone). Ported from the USB-fix branch.
- **USB when the iPhone is plugged into the machine running AltKeeper.** Every connection (check, renew, sign and install, AltServer) first looks for an iPhone on USB through the local `usbmuxd` (or the one in `USBMUXD_SOCKET_ADDRESS`) and talks to it through the CoreDeviceProxy tunnel; if there is none, or it fails, it falls back to Wi-Fi as before. Much faster for installing IPAs. Needs the phone to already trust the computer (the usual "Trust" prompt), not the remote pairing. `--phone <ip:port>` forces Wi-Fi; `ALTKEEPER_NO_USB=1` turns USB off. In Docker the usbmuxd socket must be mounted into the container.
- `ALTKEEPER_REVOKE_CERTS=1`: when installing an IPA from the web page fails with Apple error 7460 (the Apple ID already has a development certificate, e.g. from AltStore/SideStore), AltKeeper can revoke it and create its own. Off by default; without it you now get a clear explanation instead of a generic error.
- **Windows support (native, no Docker).** `cargo build --release` on Windows 10/11 produces
Expand Down
Loading
Loading