name: "Codex [reusable action]"
description: "A reusable action that runs a Codex model."

inputs:
  openai_api_key:
    description: "The value to use as the OPENAI_API_KEY environment variable when running Codex."
    required: true
  trigger_phrase:
    description: "Text to trigger Codex from a PR/issue body or comment."
    required: false
    default: ""
  github_token:
    description: "Token so Codex can comment on the PR or issue."
    required: true
  codex_args:
    description: "A whitespace-delimited list of arguments to pass to Codex. Due to limitations in YAML, arguments with spaces are not supported. For more complex configurations, use the `codex_home` input."
    required: false
    default: "--config hide_agent_reasoning=true --full-auto"
  codex_home:
    description: "Value to use as the CODEX_HOME environment variable when running Codex."
    required: false
  codex_release_tag:
    description: "The release tag of the Codex model to run, e.g., 'rust-v0.3.0'. Defaults to the latest release."
    required: false
    default: ""

runs:
  using: "composite"
  steps:
    # Do this in Bash so we do not even bother to install Bun if the sender does
    # not have write access to the repo.
    - name: Verify user has write access to the repo.
      env:
        GH_TOKEN: ${{ github.token }}
      shell: bash
      run: |
        set -euo pipefail

        PERMISSION=$(gh api \
          "/repos/${GITHUB_REPOSITORY}/collaborators/${{ github.event.sender.login }}/permission" \
          | jq -r '.permission')

        if [[ "$PERMISSION" != "admin" && "$PERMISSION" != "write" ]]; then
          exit 1
        fi

    - name: Download Codex
      env:
        GH_TOKEN: ${{ github.token }}
      shell: bash
      run: |
        set -euo pipefail

        # Determine OS/arch and corresponding Codex artifact name.
        uname_s=$(uname -s)
        uname_m=$(uname -m)

        case "$uname_s" in
          Linux*)   os="linux" ;;
          Darwin*)  os="apple-darwin" ;;
          *) echo "Unsupported operating system: $uname_s"; exit 1 ;;
        esac

        case "$uname_m" in
          x86_64*) arch="x86_64" ;;
          arm64*|aarch64*) arch="aarch64" ;;
          *) echo "Unsupported architecture: $uname_m"; exit 1 ;;
        esac

        # linux builds differentiate between musl and gnu.
        if [[ "$os" == "linux" ]]; then
          if [[ "$arch" == "x86_64" ]]; then
            triple="${arch}-unknown-linux-musl"
          else
            # Only other supported linux build is aarch64 gnu.
            triple="${arch}-unknown-linux-gnu"
          fi
        else
          # macOS
          triple="${arch}-apple-darwin"
        fi

        # Note that if we start baking version numbers into the artifact name,
        # we will need to update this action.yml file to match.
        artifact="codex-exec-${triple}.tar.gz"

        TAG_ARG="${{ inputs.codex_release_tag }}"
        # The usage is `gh release download [<tag>] [flags]`, so if TAG_ARG
        # is empty, we do not pass it so we can default to the latest release.
        gh release download ${TAG_ARG:+$TAG_ARG} --repo openai/codex \
          --pattern "$artifact" --output - \
        | tar xzO > /usr/local/bin/codex-exec
        chmod +x /usr/local/bin/codex-exec

        # Display Codex version to confirm binary integrity; ensure we point it
        # at the checked-out repository via --cd so that any subsequent commands
        # use the correct working directory.
        codex-exec --cd "$GITHUB_WORKSPACE" --version

    - name: Install Bun
      uses: oven-sh/setup-bun@v2
      with:
        bun-version: 1.2.11

    - name: Install dependencies
      shell: bash
      run: |
        cd ${{ github.action_path }}
        bun install --production

    - name: Run Codex
      shell: bash
      run: bun run ${{ github.action_path }}/src/main.ts
      # Process args plus environment variables often have a max of 128 KiB,
      # so we should fit within that limit?
      env:
        INPUT_CODEX_ARGS: ${{ inputs.codex_args || '' }}
        INPUT_CODEX_HOME: ${{ inputs.codex_home || ''}}
        INPUT_TRIGGER_PHRASE: ${{ inputs.trigger_phrase || '' }}
        OPENAI_API_KEY: ${{ inputs.openai_api_key }}
        GITHUB_TOKEN: ${{ inputs.github_token }}
        GITHUB_EVENT_ACTION: ${{ github.event.action || '' }}
        GITHUB_EVENT_LABEL_NAME: ${{ github.event.label.name || '' }}
        GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number || '' }}
        GITHUB_EVENT_ISSUE_BODY: ${{ github.event.issue.body || '' }}
        GITHUB_EVENT_REVIEW_BODY: ${{ github.event.review.body || '' }}
        GITHUB_EVENT_COMMENT_BODY: ${{ github.event.comment.body || '' }}
