Aggiunge action triage-issue e workflow di test #2
22
.gitea/workflows/triage-issue.yml
Normal file
22
.gitea/workflows/triage-issue.yml
Normal file
@@ -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 }}
|
||||
145
triage-issue/action.yml
Normal file
145
triage-issue/action.yml
Normal file
@@ -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<<EOF"
|
||||
echo "$COMMENT"
|
||||
echo "EOF"
|
||||
} >> "$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"
|
||||
Reference in New Issue
Block a user