day-piece-camera 0.1.0

A camera viewfinder with photo capture for Day apps on iOS, Android and HarmonyOS
Documentation
name: ci

# Three questions, answered on every push and once a day:
#   host        does the crate build, lint, and pass its host tests?
#   cross-check do the native halves compile for the targets they claim?
#   demo        does the walkthrough pass on the iOS Simulator, the Android emulator and the
#               HarmonyOS emulator, against day's main or newest release?
#
# No Cargo.lock is committed, here or in demo/: every run resolves day afresh. A push builds against the
# head of day's main (and of every other Day repository it uses), and the nightly run against
# the newest releases on crates.io (daybrite/actions' day-deps). A red push run after a day push
# is the signal, not a nuisance; a red nightly run means this crate needs a day that is not
# released yet. There is no pinned lock for a local `day patch` table to rewrite and commit by
# accident.
on:
  push:
    branches: ["**"]
    tags: ["v[0-9]+.[0-9]+.[0-9]+*"]
  pull_request:
  workflow_dispatch:
    inputs:
      day-main:
        description: Build against day's main branch instead of the newest release
        type: boolean
        default: false
  schedule:
    # Daily: day's main moves, and so does CameraX, on weeks nobody pushes.
    - cron: "0 7 * * *"

# The repository's own jobs run this checkout's code with a read-only token. The write grants
# sit on the job that calls the shared workflow, whose release and Pages jobs alone use them;
# its build legs, which run this code too, narrow their token to read-only themselves.
permissions:
  contents: read

jobs:
  host:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: dtolnay/rust-toolchain@stable
      # Day from crates.io, or from main on a push (daybrite/actions day-deps).
      - uses: daybrite/actions/.github/actions/day-deps@v1
        with:
          day-deps: ${{ inputs.day-main && 'main' || 'auto' }}
      - run: cargo fmt --all -- --check
      - run: cargo clippy --all-targets -- -D warnings
      # The pure half: report decoding, photo payloads, state labels.
      - run: cargo test

  # The native halves compile for their targets. A link is not attempted here (the demo below
  # does that inside a real app), but an objc2 call that no longer type-checks, a JNI signature
  # drift in the Android arm, or a C shim that stopped matching the NDK headers fails here in a
  # minute rather than in an emulator.
  cross-check:
    strategy:
      fail-fast: false
      matrix:
        include:
          - { os: macos-15, target: aarch64-apple-ios-sim, features: uikit }
          - { os: ubuntu-latest, target: aarch64-linux-android, features: material }
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v7
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      # Day from crates.io, or from main on a push (daybrite/actions day-deps).
      - uses: daybrite/actions/.github/actions/day-deps@v1
        with:
          day-deps: ${{ inputs.day-main && 'main' || 'auto' }}
      - run: cargo clippy --target ${{ matrix.target }} --features ${{ matrix.features }} -- -D warnings

  # The proof: the demo app, driven end to end on each platform by the shared Day workflow. It
  # builds against day's main or newest release, runs the walkthrough, and fails on a failed assertion or a
  # blank capture. Screenshots are uploaded per target, and a tag build attaches them to the
  # release. The HarmonyOS leg is where the C shim meets the NDK and links.
  #
  # Two walkthroughs. dayscript/camera.yaml asserts the page as a first launch shows it, with
  # the permission undecided: the Allow button raises an OS dialog a dayscript cannot dismiss,
  # so the viewfinder stays idle there. On Android the emulator has a virtual camera, so that leg
  # launches with the permission already granted (`grant-permissions` becomes `day launch
  # --grant camera`, which marks it with `pm grant` between the install and the start) and runs
  # dayscript/camera-capture.yaml instead: the session runs, the shutter writes a photo, the page
  # shows it, and the other camera comes up. The iOS Simulator has no camera at all, so the CLI
  # refuses a camera grant there, and the walkthrough stays the first-launch one.
  demo:
    uses: daybrite/actions/.github/workflows/dayapp.yml@v1
    permissions:
      contents: write # release-asset upload on tag builds
      id-token: write # crates.io Trusted Publishing (publish-crates)
    secrets: inherit
    with:
      project-path: demo
      targets: ios-uikit, android-material, harmony-arkui
      day-deps: ${{ inputs.day-main && 'main' || 'auto' }}
      # On a version tag, after every leg passed: the library crates to crates.io.
      publish-crates: true
      scripts: dayscript/camera.yaml
      target-scripts: |
        android-material: dayscript/camera-capture.yaml
      grant-permissions: |
        android-material: camera
      preflight-checks: fmt, clippy, test
      ios-devices: |
        device=iPhone, orientation=portrait
      android-devices: |
        device=pixel_7,     os=36, orientation=portrait