|
| 1 | +name: tmp podfile lock proof |
| 2 | + |
| 3 | +on: |
| 4 | + push: |
| 5 | + branches: [fix/kilo-app-upload-marker-race] |
| 6 | + paths: ['.github/workflows/tmp-podfile-lock-proof.yml'] |
| 7 | + |
| 8 | +permissions: |
| 9 | + contents: read |
| 10 | + |
| 11 | +jobs: |
| 12 | + proof: |
| 13 | + runs-on: ${{ vars.RUNNER_DEFAULT_LABEL || 'ubuntu-latest' }} |
| 14 | + timeout-minutes: 60 |
| 15 | + steps: |
| 16 | + - uses: useblacksmith/checkout@41cdeedae8edb2e684ba22896a5fd2a3cb85db6b # v1 |
| 17 | + with: |
| 18 | + lfs: true |
| 19 | + - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 |
| 20 | + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 |
| 21 | + with: |
| 22 | + node-version-file: '.nvmrc' |
| 23 | + cache: 'pnpm' |
| 24 | + - run: pnpm install --frozen-lockfile |
| 25 | + - name: EAS iOS production build (no submission) |
| 26 | + working-directory: apps/mobile |
| 27 | + env: |
| 28 | + EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} |
| 29 | + run: | |
| 30 | + pnpx eas-cli@21.8.0 build --profile production --platform ios --non-interactive --json --wait > build.json |
| 31 | + echo "artifacts keys: $(jq -c '[.[] | {platform, keys: (.artifacts | keys)}]' build.json)" |
| 32 | + - name: Download and read the Podfile.lock the way the release job does |
| 33 | + working-directory: apps/mobile |
| 34 | + env: |
| 35 | + EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} |
| 36 | + run: | |
| 37 | + mkdir -p artifacts |
| 38 | + download() { |
| 39 | + url="$1"; out="$2"; label="$3" |
| 40 | + if curl -fL -H "Authorization: Bearer $EXPO_TOKEN" -o "$out" "$url"; then |
| 41 | + echo "$label: downloaded with Authorization header" |
| 42 | + elif curl -fL -o "$out" "$url"; then |
| 43 | + echo "$label: downloaded without Authorization header" |
| 44 | + else |
| 45 | + echo "::error::$label download failed"; return 1 |
| 46 | + fi |
| 47 | + } |
| 48 | + download "$(jq -r '.[] | select(.platform=="IOS") | .artifacts.applicationArchiveUrl' build.json)" artifacts/app.ipa "iOS" |
| 49 | + download "$(jq -r '.[] | select(.platform=="IOS") | .artifacts.buildArtifactsUrl' build.json)" artifacts/ios-build-artifacts "iOS build artifacts" |
| 50 | + file artifacts/ios-build-artifacts |
| 51 | + if gzip -t artifacts/ios-build-artifacts 2>/dev/null; then |
| 52 | + echo "archive members:"; tar -tzf artifacts/ios-build-artifacts |
| 53 | + MEMBER=$(tar -tzf artifacts/ios-build-artifacts | grep -E '(^|/)Podfile\.lock$' || true) |
| 54 | + if [ "$(printf '%s' "$MEMBER" | grep -c '')" -ne 1 ]; then |
| 55 | + echo "::error::the iOS build artifacts archive must hold exactly one Podfile.lock, found: ${MEMBER:-none}" |
| 56 | + exit 1 |
| 57 | + fi |
| 58 | + tar -xzf artifacts/ios-build-artifacts -O "$MEMBER" > artifacts/Podfile.lock |
| 59 | + else |
| 60 | + mv artifacts/ios-build-artifacts artifacts/Podfile.lock |
| 61 | + fi |
| 62 | + grep -q '^PODS:' artifacts/Podfile.lock |
| 63 | + node --input-type=module -e " |
| 64 | + import { readPodfileLockComponents, readIpaComponents } from '../../scripts/mobile-sbom-ipa.mjs'; |
| 65 | + const pods = readPodfileLockComponents({ podfileLockPath: 'artifacts/Podfile.lock' }).components; |
| 66 | + const ipa = readIpaComponents({ ipaPath: 'artifacts/app.ipa' }); |
| 67 | + const scan = Array.isArray(ipa) ? ipa : ipa.components; |
| 68 | + console.log('lockfile pods:', pods.length, 'ipa scan components:', scan.length); |
| 69 | + console.log('sample:', pods.filter(p => /^(React-Core|hermes-engine|RNSentry|EXConstants)$/.test(p.name)).map(p => p.purl).join(' ')); |
| 70 | + " |
0 commit comments