infra :: gemini git workflow 2차 수정 #483
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: '📋 Gemini Scheduled Issue Triage' | |
| on: | |
| schedule: | |
| - cron: '0 * * * *' | |
| pull_request: | |
| branches: [chatforyou_v2] | |
| paths: ['.github/workflows/gemini-scheduled-triage.yml'] | |
| push: | |
| branches: [chatforyou_v2] | |
| paths: ['.github/workflows/gemini-scheduled-triage.yml'] | |
| workflow_dispatch: | |
| concurrency: | |
| group: '${{ github.workflow }}' | |
| cancel-in-progress: true | |
| defaults: | |
| run: | |
| shell: 'bash' | |
| jobs: | |
| triage: | |
| runs-on: 'ubuntu-latest' | |
| timeout-minutes: 7 | |
| permissions: | |
| contents: 'read' | |
| id-token: 'write' | |
| issues: 'read' | |
| pull-requests: 'read' | |
| outputs: | |
| available_labels: '${{ steps.get_labels.outputs.available_labels }}' | |
| triaged_issues: '${{ steps.collect_triage_output.outputs.triaged_issues }}' | |
| steps: | |
| - name: 'Get repository labels' | |
| id: 'get_labels' | |
| uses: 'actions/github-script@v7' | |
| with: | |
| script: |- | |
| const labels = []; | |
| for await (const response of github.paginate.iterator(github.rest.issues.listLabelsForRepo, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| per_page: 100, | |
| })) { | |
| labels.push(...response.data); | |
| } | |
| if (!labels || labels.length === 0) { | |
| core.setFailed('There are no issue labels in this repository.') | |
| } | |
| const labelNames = labels.map(label => label.name).sort(); | |
| core.setOutput('available_labels', labelNames.join(',')); | |
| core.info(`Found ${labelNames.length} labels: ${labelNames.join(', ')}`); | |
| return labelNames; | |
| - name: 'Find untriaged issues' | |
| id: 'find_issues' | |
| env: | |
| GITHUB_REPOSITORY: '${{ github.repository }}' | |
| GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN || github.token }}' | |
| run: |- | |
| ISSUES="$(gh issue list \ | |
| --state 'open' \ | |
| --search 'no:label OR label:"status/needs-triage"' \ | |
| --json number,title,body \ | |
| --limit '100' \ | |
| --repo "${GITHUB_REPOSITORY}" \ | |
| | jq -c '.' | |
| )" | |
| echo "issues_to_triage=${ISSUES}" >> "${GITHUB_OUTPUT}" | |
| - name: 'Run Gemini Issue Analysis' | |
| id: 'gemini_issue_analysis' | |
| if: |- | |
| ${{ steps.find_issues.outputs.issues_to_triage != '[]' }} | |
| uses: 'google-github-actions/run-gemini-cli@v0' | |
| env: | |
| GITHUB_TOKEN: '' | |
| ISSUES_TO_TRIAGE: '${{ steps.find_issues.outputs.issues_to_triage }}' | |
| REPOSITORY: '${{ github.repository }}' | |
| AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}' | |
| GEMINI_TRUST_WORKSPACE: 'true' | |
| with: | |
| gemini_api_key: '${{ secrets.GEMINI_API_KEY }}' | |
| gemini_cli_version: '${{ vars.GEMINI_CLI_VERSION }}' | |
| gemini_debug: '${{ fromJSON(vars.GEMINI_DEBUG || vars.ACTIONS_STEP_DEBUG || false) }}' | |
| gemini_model: '${{ vars.GEMINI_MODEL }}' | |
| upload_artifacts: '${{ vars.UPLOAD_ARTIFACTS }}' | |
| workflow_name: 'gemini-scheduled-triage' | |
| settings: |- | |
| { | |
| "model": { | |
| "maxSessionTurns": 25 | |
| }, | |
| "telemetry": { | |
| "enabled": true, | |
| "target": "local", | |
| "outfile": ".gemini/telemetry.log" | |
| }, | |
| "tools": { | |
| "core": [ | |
| "run_shell_command(echo)", | |
| "run_shell_command(jq)", | |
| "run_shell_command(printenv)" | |
| ] | |
| } | |
| } | |
| prompt: '/gemini-scheduled-triage' | |
| - name: 'Collect triage output' | |
| id: 'collect_triage_output' | |
| if: |- | |
| ${{ steps.find_issues.outputs.issues_to_triage != '[]' }} | |
| env: | |
| TRIAGED_ISSUES: '${{ env.TRIAGED_ISSUES }}' | |
| run: |- | |
| TRIAGED_ISSUES_COMPACT="$(echo "${TRIAGED_ISSUES:-[]}" | jq -c '.')" | |
| echo "triaged_issues=${TRIAGED_ISSUES_COMPACT}" >> "${GITHUB_OUTPUT}" | |
| label: | |
| runs-on: 'ubuntu-latest' | |
| needs: [triage] | |
| if: |- | |
| needs.triage.outputs.available_labels != '' && | |
| needs.triage.outputs.triaged_issues != '' && | |
| needs.triage.outputs.triaged_issues != '[]' | |
| permissions: | |
| contents: 'read' | |
| issues: 'write' | |
| pull-requests: 'write' | |
| steps: | |
| - name: 'Mint identity token' | |
| id: 'mint_identity_token' | |
| if: |- | |
| ${{ vars.APP_ID }} | |
| uses: 'actions/create-github-app-token@v2' | |
| with: | |
| app-id: '${{ vars.APP_ID }}' | |
| private-key: '${{ secrets.APP_PRIVATE_KEY }}' | |
| permission-contents: 'read' | |
| permission-issues: 'write' | |
| permission-pull-requests: 'write' | |
| - name: 'Apply labels' | |
| env: | |
| AVAILABLE_LABELS: '${{ needs.triage.outputs.available_labels }}' | |
| TRIAGED_ISSUES: '${{ needs.triage.outputs.triaged_issues }}' | |
| uses: 'actions/github-script@v7' | |
| with: | |
| github-token: '${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}' | |
| script: |- | |
| const availableLabels = (process.env.AVAILABLE_LABELS || '').split(',') | |
| .map((label) => label.trim()) | |
| .sort() | |
| const triagedIssues = JSON.parse(process.env.TRIAGED_ISSUES || '[]') | |
| for (const issue of triagedIssues) { | |
| if (!issue || !issue.issue_number) continue; | |
| let labelsToSet = (issue.labels_to_set || []) | |
| .map((label) => label.trim()) | |
| .filter((label) => availableLabels.includes(label)) | |
| .sort() | |
| if (labelsToSet.length === 0) continue; | |
| await github.rest.issues.setLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.issue_number, | |
| labels: labelsToSet, | |
| }); | |
| } |