From 36ce1b55fb50e4302578bb22396f6d763583ea40 Mon Sep 17 00:00:00 2001 From: alberto Date: Sat, 30 May 2026 22:41:57 +0200 Subject: [PATCH] Aggiunge action triage-issue e workflow di test --- .gitea/workflows/triage-issue.yml | 22 +++++ triage-issue/action.yml | 145 ++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 .gitea/workflows/triage-issue.yml create mode 100644 triage-issue/action.yml diff --git a/.gitea/workflows/triage-issue.yml b/.gitea/workflows/triage-issue.yml new file mode 100644 index 0000000..ece519f --- /dev/null +++ b/.gitea/workflows/triage-issue.yml @@ -0,0 +1,22 @@ +name: Triage Issue + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: ./install-opencode + + - uses: ./triage-issue + with: + issue-title: ${{ github.event.issue.title }} + issue-body: ${{ github.event.issue.body }} + issue-number: ${{ github.event.issue.number }} + repository: ${{ github.repository }} + api-token: ${{ secrets.GITEA_TOKEN }} + api-key: ${{ secrets.OPencode_API_KEY }} diff --git a/triage-issue/action.yml b/triage-issue/action.yml new file mode 100644 index 0000000..06d4413 --- /dev/null +++ b/triage-issue/action.yml @@ -0,0 +1,145 @@ +name: Triage Issue +description: Analizza una issue con opencode e la classifica come bug o richiesta. + +inputs: + issue-title: + description: Titolo dell'issue. + required: true + issue-body: + description: Corpo dell'issue. + required: true + issue-number: + description: Numero dell'issue. + required: true + repository: + description: Repository in formato owner/repo. + required: true + api-token: + description: Token API Gitea. + required: true + gitea-host: + description: URL del server Gitea. + required: false + default: "https://git.incloud.ovh" + api-key: + description: API key per opencode. + required: true + model: + description: Modello AI in formato provider/model. + required: false + default: "" + +outputs: + label: + description: Label attribuita (bug o richiesta). + value: ${{ steps.classifica.outputs.label }} + comment: + description: Commento di triage pubblicato. + value: ${{ steps.classifica.outputs.comment }} + +runs: + using: composite + steps: + - name: Configura autenticazione opencode + shell: bash + run: | + set -euo pipefail + mkdir -p ~/.local/share/opencode + jq -n \ + --arg provider "opencode-go" \ + --arg key "${{ inputs.api-key }}" \ + '{($provider): {type: "api", key: $key}}' > ~/.local/share/opencode/auth.json + chmod 600 ~/.local/share/opencode/auth.json + + - name: Classifica issue + id: classifica + shell: bash + run: | + set -euo pipefail + + HOST="${{ inputs.gitea-host }}" + TOKEN="${{ inputs.api-token }}" + REPO="${{ inputs.repository }}" + ISSUE_NUM="${{ inputs.issue-number }}" + MODEL_ARG=() + [ -n "${{ inputs.model }}" ] && MODEL_ARG=(--model "${{ inputs.model }}") + + BODY="$(echo "${{ inputs.issue-body }}" | head -c 10000)" + [ "${#BODY}" -ge 10000 ] && BODY+=$'\n... (troncato)' + + read -r -d '' PROMPT << 'PROMPT_EOF' || true +Sei un sistema di triage automatico per repository software. + +Analizza la seguente issue e classificala con UNA delle label disponibili: +- "bug": malfunzionamento, errore, crash, anomalia, comportamento inaspettato +- "richiesta": nuova funzionalità, miglioramento, refactoring, ottimizzazione, o dubbio + +Rispondi ESCLUSIVAMENTE con un JSON valido su una singola riga, senza nessun altro testo: + +{"label":"bug","comment":"Breve analisi in italiano..."} + +Titolo: ${{ inputs.issue-title }} +Corpo: +$BODY +PROMPT_EOF + + OUTFILE="$GITHUB_WORKSPACE/opencode-triage.txt" + opencode run "$PROMPT" "${MODEL_ARG[@]}" --dangerously-skip-permissions 2>&1 | tee "$OUTFILE" + + RESPONSE=$(cat "$OUTFILE") + + JSON="" + if echo "$RESPONSE" | jq empty 2>/dev/null; then + JSON="$RESPONSE" + elif JSON=$(echo "$RESPONSE" | grep -oP '\{"label":\s*"(bug|richiesta)".*?"comment":\s*".*?"\s*}' | head -1); then + : + elif JSON=$(echo "$RESPONSE" | grep -oP '\{[^}]*\}' | head -1); then + : + fi + + if [ -z "$JSON" ] || ! echo "$JSON" | jq empty 2>/dev/null; then + echo "WARN: Impossibile estrarre JSON valido, default a richiesta" + LABEL="richiesta" + COMMENT="Classificazione automatica non riuscita. Label impostata a richiesta per default." + else + LABEL=$(echo "$JSON" | jq -r '.label // "richiesta"') + COMMENT=$(echo "$JSON" | jq -r '.comment // "Classificazione automatica."') + fi + + case "$LABEL" in + bug|richiesta) ;; + *) echo "WARN: Label '$LABEL' sconosciuta, default a richiesta"; LABEL="richiesta" ;; + esac + + echo "label=$LABEL" >> "$GITHUB_OUTPUT" + { + echo "comment<> "$GITHUB_OUTPUT" + + echo "Label determinata: $LABEL" + + LABEL_ID=$(curl -sS -f "$HOST/api/v1/repos/$REPO/labels" \ + -H "Authorization: token $TOKEN" \ + -H "Accept: application/json" \ + 2>/dev/null | jq -r ".[] | select(.name==\"$LABEL\") | .id" | head -1) + + if [ -n "$LABEL_ID" ]; then + curl -sS -X PUT "$HOST/api/v1/repos/$REPO/issues/$ISSUE_NUM/labels" \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"labels\":[$LABEL_ID]}" 2>/dev/null && \ + echo "Label '$LABEL' applicata" || \ + echo "WARN: Impossibile applicare la label '$LABEL'" + else + echo "WARN: Label '$LABEL' non trovata nel repo. Creala manualmente o passa un token con permessi." + fi + + COMMENT_JSON=$(jq -n --arg body "$COMMENT" '{body: $body}') + curl -sS -X POST "$HOST/api/v1/repos/$REPO/issues/$ISSUE_NUM/comments" \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/json" \ + -d "$COMMENT_JSON" 2>/dev/null && \ + echo "Commento pubblicato sull'issue #$ISSUE_NUM" || \ + echo "WARN: Impossibile pubblicare il commento"