# Acțiunea GitHub (/ro/docs/resolve/github-action)

Instalezi acțiunea Codai Resolve — etichetezi un issue codai-fix și primești un PR cu un fix verificat și o atestare publică. Intrări, ieșiri, secrete, permisiuni și workflow-uri exemplu.

Acțiunea stă la [`dragoscv/resolve-action`](https://github.com/dragoscv/resolve-action). Rulează pe un **eveniment `issues`**, trimite issue-ul către Resolve, acceptă cotația dacă workflow-ul tău permite, așteaptă verdictul și, la succes, publică un branch `codai-fix/issue-<N>` și deschide un pull request care leagă atestarea publică. La refuz sau eșec comentează motivul pe issue. Nu se facturează nimic dacă nu a fost verificat un fix.

## Utilizare [#utilizare]

```yaml title=".github/workflows/codai-fix.yml"
name: codai-fix
on:
  issues:
    types: [labeled]

permissions:
  contents: write
  pull-requests: write
  issues: write

jobs:
  resolve:
    if: github.event.label.name == 'codai-fix'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: dragoscv/resolve-action@v1
        with:
          codai-api-key: ${{ secrets.CODAI_API_KEY }}
          # Opțional — plătește automat cotațiile fixe până la un prag (7 € / 19 € / 49 €):
          # auto-accept: 'true'
          # max-tier: 't19'
```

<Steps>
<Step>

### Adaugi secretul [#adaugi-secretul]

Creezi o cheie la [hub.codai.ro](https://hub.codai.ro) → **Keys** și o stochezi ca secret de repository **`CODAI_API_KEY`** (*Settings → Secrets and variables → Actions*). Cheile arată ca `codai_xxxxxxxx`.

</Step>
<Step>

### Creezi eticheta [#creezi-eticheta]

Adaugi o etichetă numită exact **`codai-fix`** în repository. Garda `if:` din workflow face ca alte etichete să nu pornească niciodată un job.

</Step>
<Step>

### Etichetezi un issue [#etichetezi-un-issue]

Aplici `codai-fix` pe un issue cu o descriere clară a bug-ului. Acțiunea comentează într-un minut cu rezultatul triajului; un fix verificat sosește ca PR, de regulă în 5–20 de minute.

</Step>
</Steps>

## Intrări [#intrări]

<TypeTable
  type={{
    'codai-api-key': { type: 'string', description: 'Cheie API codai (codai_…). O stochezi ca secret.', required: true },
    'github-token': { type: 'string', description: 'Token folosit pentru a comenta pe issue, a publica branch-ul de fix și a deschide PR-ul. Are nevoie de contents + pull-requests write.', default: '${{ github.token }}' },
    'resolve-base-url': { type: 'string', description: 'URL de bază al API-ului Resolve. Schimbi doar pentru un Resolve auto-găzduit.', default: 'https://resolve.codai.ro' },
    'auto-accept': { type: "'true' | 'false'", description: 'Acceptă automat cotațiile plătite. Când este false, rulează doar job-urile din nivelul gratuit; cotațiile plătite sunt comentate pe issue și nu rulează nimic.', default: 'false' },
    'max-tier': { type: "'t7' | 't19' | 't49'", description: 'Cel mai înalt prag de cotație acceptat automat (7 € / 19 € / 49 €). O cotație peste el este comentată, nu rulată.', default: 't7' },
  }}
/>

## Ieșiri [#ieșiri]

<TypeTable
  type={{
    status: { type: "'resolved' | 'failed' | 'error' | 'declined' | 'quoted'", description: "Statusul final al job-ului. 'quoted' înseamnă că o cotație plătită nu a fost acceptată automat." },
    'pr-url': { type: 'string', description: 'URL-ul pull request-ului deschis. Setat doar când este resolved.' },
    'attestation-url': { type: 'string', description: 'JSON-ul public de dovadă (https://resolve.codai.ro/v1/resolve/attestations/<id>). Setat doar când este resolved.' },
  }}
/>

## Permisiuni [#permisiuni]

Workflow-ul are nevoie de trei scope-uri de scriere pe `GITHUB_TOKEN`-ul implicit:

| Scope | Folosit pentru |
| --- | --- |
| `contents: write` | Publică branch-ul `codai-fix/issue-<N>` cu patch-ul. |
| `pull-requests: write` | Deschide PR-ul către branch-ul implicit. |
| `issues: write` | Comentează cotația, motivul refuzului sau motivul eșecului pe issue. |

Dacă organizația ta restricționează token-ul implicit la doar-citire, fie activezi *Read and write permissions* în *Settings → Actions → General → Workflow permissions*, fie treci un PAT cu permisiuni fine ca `github-token`.

`actions/checkout` cu `fetch-depth: 0` contează: acțiunea comite patch-ul peste istoricul extras și are nevoie de clona completă pentru a publica un branch.

## Ce face acțiunea, pas cu pas [#ce-face-acțiunea-pas-cu-pas]

1. Citește `issue.title` + `issue.body` din payload-ul evenimentului (primele 50 000 de caractere) și le trimite prin `POST` cu `repo_url: https://github.com/<owner>/<repo>` la `/v1/resolve/jobs`.
2. **Refuzat** → comentează *Codai Resolve declined this issue (nothing billed)* cu motivul; `status=declined`.
3. **Cotat** → dacă `auto-accept` este dezactivat, sau pragul este peste `max-tier`, comentează prețul și cum îl activezi; `status=quoted`, nu rulează nimic. Altfel `POST …/accept`.
4. Interoghează `GET /v1/resolve/jobs/{id}` la fiecare 15 secunde, până la **25 de minute**.
5. **Rezolvat** → preia atestarea, aplică `patch` pe un branch nou `codai-fix/issue-<N>`, îl publică, deschide PR-ul (corpul leagă atestarea și citează testul de reproducere), comentează pe issue; setează `pr-url` și `attestation-url`.
6. **Eșuat / eroare** → comentează *Codai Resolve could not verify a fix (nothing billed)* cu `fail_reason`.

## Workflow-uri exemplu [#workflow-uri-exemplu]

### Plătești automat până la 19 € [#plătești-automat-până-la-19-]

```yaml title=".github/workflows/codai-fix.yml"
name: codai-fix
on:
  issues:
    types: [labeled]
permissions:
  contents: write
  pull-requests: write
  issues: write
jobs:
  resolve:
    if: github.event.label.name == 'codai-fix'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - uses: dragoscv/resolve-action@v1
        with:
          codai-api-key: ${{ secrets.CODAI_API_KEY }}
          auto-accept: 'true'
          max-tier: 't19'
```

### Rulezi la un job CI eșuat [#rulezi-la-un-job-ci-eșuat]

Acțiunea citește issue-ul din **payload-ul evenimentului**, așa că declanșatorul trebuie să fie un eveniment `issues`. Pentru a reacționa la un run CI roșu, workflow-ul care eșuează deschide (sau etichetează) un issue, iar workflow-ul `codai-fix` de mai sus îl preia:

```yaml title=".github/workflows/ci.yml (fragment)"
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pnpm install --frozen-lockfile
      - id: tests
        run: pnpm test
      - name: Cere lui Resolve să repare
        if: failure()
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          gh issue create \
            --title "CI failed on ${GITHUB_REF_NAME} (${GITHUB_SHA::7})" \
            --body "Run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}
          Job \`test\` failed. Please reproduce and fix." \
            --label codai-fix
```

Dă-i și acestui job `issues: write`. Lipești output-ul relevant al testelor în corp când poți — triajul cotează din textul pe care îl vede, iar un eșec precis primește un prag mai ieftin.

### Declanșare manuală [#declanșare-manuală]

`workflow_dispatch` nu poartă niciun issue, așa că acțiunea nu poate rula direct sub el. O împachetezi: iei un număr de issue ca intrare și re-etichetezi issue-ul, ceea ce declanșează workflow-ul `issues: labeled`.

```yaml title=".github/workflows/codai-fix-manual.yml"
name: codai-fix (manual)
on:
  workflow_dispatch:
    inputs:
      issue:
        description: Numărul issue-ului de trimis la Resolve
        required: true
permissions:
  issues: write
jobs:
  relabel:
    runs-on: ubuntu-latest
    steps:
      - env:
          GH_TOKEN: ${{ github.token }}
        run: |
          gh issue edit ${{ inputs.issue }} --remove-label codai-fix || true
          gh issue edit ${{ inputs.issue }} --add-label codai-fix
```

### Folosești ieșirile [#folosești-ieșirile]

```yaml
      - id: fix
        uses: dragoscv/resolve-action@v1
        with:
          codai-api-key: ${{ secrets.CODAI_API_KEY }}
      - if: steps.fix.outputs.status == 'resolved'
        run: echo "PR ${{ steps.fix.outputs['pr-url'] }} — dovadă ${{ steps.fix.outputs['attestation-url'] }}"
```

<Callout type="warn">
Timpul runner-ului se contorizează pe minutele tale GitHub Actions cât timp acțiunea interoghează (până la 25 de minute pe un job lent). Resolve în sine facturează doar la un fix verificat.
</Callout>

<Cards>
  <Card title="Cum funcționează" href="./how-it-works.mdx" description="Ce se întâmplă între accept și resolved." />
  <Card title="Prețuri și limite" href="./pricing-and-limits.mdx" description="Praguri, remedieri gratuite, plafoane." />
  <Card title="Referință API" href="../api/resolve.mdx" description="Apelezi Resolve fără GitHub." />
</Cards>
