name: Update Nix upstream hashes

on:
  schedule:
    - cron: '0 * * * *'
  workflow_dispatch: {}

permissions:
  actions: write
  contents: write
  pull-requests: write

concurrency:
  group: update-nix-upstream-hashes
  cancel-in-progress: false

jobs:
  update-hash:
    runs-on: ubuntu-latest
    timeout-minutes: 90
    env:
      NIX_CONFIG: experimental-features = nix-command flakes
      CACHIX_CACHE_NAME: codex-desktop-linux
      CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
      FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 24

      - uses: cachix/install-nix-action@v31

      - name: Configure Cachix for hash refresh builds
        if: env.CACHIX_AUTH_TOKEN != ''
        uses: cachix/cachix-action@v17
        with:
          name: ${{ env.CACHIX_CACHE_NAME }}
          authToken: ${{ env.CACHIX_AUTH_TOKEN }}

      - name: Install validation dependencies
        run: |
          set -euo pipefail
          sudo apt-get update
          sudo apt-get install -y p7zip-full

      - name: Refresh Nix upstream hash
        run: scripts/ci/update-nix-hashes.sh

      - name: Open refreshed hashes pull request
        env:
          GH_TOKEN: ${{ github.token }}
          REFRESH_BRANCH: codex/nix-upstream-refresh
        run: |
          set -euo pipefail

          if git diff --quiet -- flake.nix nix/native-modules/package.json nix/native-modules/package-lock.json; then
            echo "Nix pins unchanged, nothing to do."
            exit 0
          fi

          CODEX_DMG_HASH="$(scripts/ci/update-nix-hashes.sh read-flake-hash 'codexDmg = pkgs.fetchurl {' 'hash = ')"
          CODEX_VERSION="$(scripts/ci/update-nix-hashes.sh read-flake-string codexVersion)"
          APPCAST_VERSION="$(scripts/ci/update-nix-hashes.sh read-appcast-version 2>/dev/null || true)"
          if [ -n "$APPCAST_VERSION" ] && [ "$APPCAST_VERSION" != "$CODEX_VERSION" ]; then
            APPCAST_NOTE="- warning: Sparkle appcast currently advertises \`$APPCAST_VERSION\`, while current \`Codex.dmg\` contains \`$CODEX_VERSION\`; this PR follows the verified DMG payload."
          elif [ -n "$APPCAST_VERSION" ]; then
            APPCAST_NOTE="- Sparkle appcast also advertises \`$APPCAST_VERSION\`."
          else
            APPCAST_NOTE="- Sparkle appcast version could not be read during PR creation; pins follow the verified DMG payload."
          fi

          git config user.name  "codex-dmg-hash-bot"
          git config user.email "actions@github.com"
          git checkout -B "$REFRESH_BRANCH"
          git add flake.nix nix/native-modules/package.json nix/native-modules/package-lock.json
          git commit \
            -m "fix(nix): refresh upstream Nix pins${CODEX_VERSION:+ for $CODEX_VERSION}" \
            -m "Refreshed Codex.dmg SRI hash to $CODEX_DMG_HASH and synced codexVersion / electronVersion / native-module pins to the current upstream DMG." \
            -m "Verified all Codex Desktop Nix package outputs against the refreshed DMG." \
            -m "[skip ci]"
          git push --force origin "$REFRESH_BRANCH"

          pr_body="$RUNNER_TEMP/nix-refresh-pr-body.md"
          cat >"$pr_body" <<EOF
          ## Summary
          - refresh Codex.dmg hash and upstream version pins to the current upstream DMG
          - update Electron fixed-output hashes when electronVersion changes
          - regenerate nix/native-modules/package-lock.json when native module pins change
          $APPCAST_NOTE

          ## Validation
          - this workflow verified all Codex Desktop Nix package outputs before opening the PR
          - refreshed Codex.dmg SRI hash: \`$CODEX_DMG_HASH\`
          EOF

          pr_url="$(gh pr list --repo "$GITHUB_REPOSITORY" --base main --head "$REFRESH_BRANCH" --state open --json url --jq '.[0].url // ""')"
          if [ -z "$pr_url" ]; then
            pr_url="$(gh pr create \
              --repo "$GITHUB_REPOSITORY" \
              --base main \
              --head "$REFRESH_BRANCH" \
              --title "fix(nix): refresh upstream Nix pins${CODEX_VERSION:+ for $CODEX_VERSION}" \
              --body-file "$pr_body")"
          else
            gh pr edit "$pr_url" \
              --title "fix(nix): refresh upstream Nix pins${CODEX_VERSION:+ for $CODEX_VERSION}" \
              --body-file "$pr_body"
          fi

          echo "Opened or updated refresh PR: $pr_url"

          # Branch pushes made with GITHUB_TOKEN do not trigger normal push/PR
          # workflows. Dispatch CI explicitly so required checks attach to the
          # bot branch head SHA and the PR can satisfy the repository ruleset.
          gh workflow run ci.yml --repo "$GITHUB_REPOSITORY" --ref "$REFRESH_BRANCH"
