98 lines
4.7 KiB
YAML
98 lines
4.7 KiB
YAML
name: Real APK signature inspection
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
build_cache_artifact:
|
|
description: Portable build cache artifact from the calling CI run.
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
remote_cache_write:
|
|
description: Trusted release qualification may publish the remote cache.
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
secrets:
|
|
TURBO_TOKEN:
|
|
description: Remote cache token. Only trusted callers pass it.
|
|
required: false
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
HUSKY: "0"
|
|
# A called workflow sees the caller event, so workflow_call is not an event
|
|
# name here. Writes when remote_cache_write is set, or on the default branch
|
|
# for push, schedule, and manual dispatch. Open pull requests stay empty-token
|
|
# and use the local cache only.
|
|
TURBO_TOKEN: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && secrets.TURBO_TOKEN || '' }}"
|
|
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
|
TURBO_CACHE: "${{ (inputs.remote_cache_write == true || (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'))) && 'local:rw,remote:rw' || 'local:rw' }}"
|
|
NODE_OPTIONS: "--max-old-space-size=768"
|
|
RAYON_NUM_THREADS: "1"
|
|
GOMAXPROCS: "2"
|
|
UV_THREADPOOL_SIZE: "2"
|
|
JAVA_TOOL_OPTIONS: "-Xmx512m -XX:ActiveProcessorCount=2"
|
|
|
|
jobs:
|
|
real-apk-signature:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 12
|
|
steps:
|
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version-file: .nvmrc
|
|
- name: Cache npm package downloads
|
|
id: npm-cache
|
|
uses: ./.github/actions/npm-cache
|
|
- run: npm ci
|
|
- uses: ./.github/actions/portable-build-cache
|
|
with:
|
|
build_cache_artifact: ${{ inputs.build_cache_artifact }}
|
|
- name: Prepare pinned SDK oracle without installing host software
|
|
shell: bash
|
|
run: |
|
|
python3 - <<'PYTHON'
|
|
import hashlib, os, urllib.request, zipfile
|
|
from pathlib import Path
|
|
root = Path(os.environ["RUNNER_TEMP"]) / "rea-apk-signature-sdk"
|
|
packages = [
|
|
("build-tools_r36.1_linux.zip", "a7b5889e4a79fcf3b0976bef40d401f4240fb1eed891d9d91169da1111e11d78", 64195204, "build-tools/36.1.0", {"apksigner", "aapt2", "lib/apksigner.jar", "source.properties"}),
|
|
("platform-36_r02.zip", "37607369a28c5b640b3a7998868d45898ebcb777565a0e85f9acf36f29631d2e", 65878410, "platforms/android-36", {"android.jar", "source.properties"}),
|
|
]
|
|
for name, expected, expected_size, directory, selected in packages:
|
|
archive = root / name
|
|
archive.parent.mkdir(parents=True, exist_ok=True)
|
|
digest = hashlib.sha256()
|
|
total = 0
|
|
with urllib.request.urlopen("https://dl.google.com/android/repository/" + name, timeout=60) as response, archive.open("wb") as output:
|
|
while chunk := response.read(1024 * 1024):
|
|
total += len(chunk)
|
|
if total > expected_size:
|
|
raise RuntimeError("SDK archive exceeds the pinned package size budget")
|
|
digest.update(chunk)
|
|
output.write(chunk)
|
|
if total != expected_size or digest.hexdigest() != expected:
|
|
raise RuntimeError("SDK oracle archive digest mismatch")
|
|
extracted = set()
|
|
with zipfile.ZipFile(archive) as source:
|
|
for entry in source.infolist():
|
|
relative = entry.filename.partition("/")[2]
|
|
if relative not in selected:
|
|
continue
|
|
target = root / directory / relative
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_bytes(source.read(entry))
|
|
target.chmod((entry.external_attr >> 16) & 0o777 or 0o644)
|
|
extracted.add(relative)
|
|
if extracted != selected:
|
|
raise RuntimeError("Pinned SDK package is missing required oracle files")
|
|
with Path(os.environ["GITHUB_ENV"]).open("a") as environment:
|
|
environment.write("ANDROID_HOME=" + str(root) + "\n")
|
|
PYTHON
|
|
- run: npm run verify:apk-signature -- --require-tools
|