[newSolution]Who can add 1 more problem of LeetCode 960 + 1problem1day comment #10
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: Daily / Sync solving label to project status | |
| # 仅对issue增删的solving标签生效: | |
| # 添加solving标签->设置Project状态为In Progress | |
| # 移除solving标签-↓ | |
| # issue为close状态->设置Project状态为Done | |
| # issue为open状态->设置Project状态为Todo | |
| # 这里GPT死活解决不了,最后分步命令之,成功了 | |
| on: | |
| issues: | |
| types: [labeled, unlabeled] | |
| permissions: | |
| issues: read | |
| repository-projects: write | |
| env: | |
| PROJECT_ID: ${{ secrets.ONE_PROBLEM_ONE_DAY_PROJECT_ID }} | |
| STATUS_FIELD_ID: ${{ secrets.ONE_PROBLEM_ONE_DAY_STATUS_FIELD_ID }} | |
| jobs: | |
| sync: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Update project status by solving label | |
| id: update-status | |
| env: | |
| GH_TOKEN: ${{ secrets.ONE_PROBLEM_ONE_DAY_PAT }} | |
| run: | | |
| echo "===== Event Debug =====" | |
| echo "action = ${{ github.event.action }}" | |
| echo "issue number = ${{ github.event.issue.number }}" | |
| echo "issue node_id = ${{ github.event.issue.node_id }}" | |
| echo "issue state = ${{ github.event.issue.state }}" | |
| echo "label(event) = ${{ github.event.label.name }}" | |
| echo "=======================" | |
| issue_node_id="${{ github.event.issue.node_id }}" | |
| issue_state="${{ github.event.issue.state }}" | |
| labels="${{ join(github.event.issue.labels.*.name, ' ') }}" | |
| echo "Current labels: $labels" | |
| has_solving=false | |
| for l in $labels; do | |
| [[ "$l" == "solving" ]] && has_solving=true | |
| done | |
| echo "has_solving = $has_solving" | |
| echo "Query project item_id via Issue.projectItems..." | |
| item_id=$(gh api graphql -f query=' | |
| query($issue:ID!) { | |
| node(id:$issue) { | |
| ... on Issue { | |
| projectItems(first:20) { | |
| nodes { | |
| id | |
| project { id } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| ' -f issue="$issue_node_id" \ | |
| --jq ".data.node.projectItems.nodes[] | |
| | select(.project.id==\"$PROJECT_ID\") | |
| | .id") | |
| if [[ -z "$item_id" ]]; then | |
| echo "Issue not in project, skip" | |
| echo "skip=true" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| echo "Found item_id = $item_id" | |
| if [[ "$has_solving" == "true" ]]; then | |
| status="In Progress" | |
| else | |
| if [[ "$issue_state" == "closed" ]]; then | |
| status="Done" | |
| else | |
| status="Todo" | |
| fi | |
| fi | |
| echo "status=$status" >> $GITHUB_OUTPUT | |
| echo "Target status name = $status" | |
| echo "Resolve status option ID..." | |
| options_json=$(gh api graphql -f query=' | |
| query($field:ID!) { | |
| node(id:$field) { | |
| ... on ProjectV2SingleSelectField { | |
| options { id name } | |
| } | |
| } | |
| }' -F field="$STATUS_FIELD_ID") | |
| option_id=$(echo "$options_json" | jq -r --arg status "$status" '.data.node.options[] | select(.name==$status) | .id') | |
| if [[ -z "$option_id" ]]; then | |
| echo "❌ Cannot find option id for status=$status" | |
| exit 1 | |
| fi | |
| echo "Resolved option_id = $option_id" | |
| echo "Update project status..." | |
| if [[ "$option_id" =~ ^[0-9]+$ ]]; then | |
| echo "纯数字 -> ID!" | |
| gql_type="ID!" | |
| # 不知道为什么,这里Done的option_id为纯数字,不论ID!还是String!都不行,折腾了好久好久 | |
| # 未验证这个能否用在In Progress和Todo上,感觉是可以的。保留if-else是为了保留这个神奇的Debug经历 | |
| gh api graphql -f query=' | |
| mutation UpdateProjectItemStatus($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) { | |
| updateProjectV2ItemFieldValue( | |
| input: { | |
| projectId: $projectId | |
| itemId: $itemId | |
| fieldId: $fieldId | |
| value: { singleSelectOptionId: $optionId } | |
| } | |
| ) { | |
| projectV2Item { | |
| id | |
| fieldValues(first: 10) { | |
| nodes { | |
| ... on ProjectV2ItemFieldSingleSelectValue { | |
| id | |
| name | |
| optionId | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| ' -f projectId="$PROJECT_ID" -f itemId="$item_id" -f fieldId="$STATUS_FIELD_ID" -f optionId="$option_id" | |
| else | |
| echo "字符串 -> String!" | |
| gql_type="String!" | |
| gh api graphql -f query=' | |
| mutation($project:ID!, $item:ID!, $field:ID!, $option:String!) { | |
| updateProjectV2ItemFieldValue(input:{ | |
| projectId:$project | |
| itemId:$item | |
| fieldId:$field | |
| value:{ singleSelectOptionId:$option } | |
| }) { | |
| projectV2Item { id } | |
| } | |
| } | |
| ' \ | |
| -F project="$PROJECT_ID" \ | |
| -F item="$item_id" \ | |
| -F field="$STATUS_FIELD_ID" \ | |
| -F option="$option_id" | |
| fi | |
| echo "Status updated successfully ✅" | |
| - name: Resolve workflow path | |
| id: resolve-workflow-path | |
| if: steps.update-status.outputs.skip != 'true' | |
| env: | |
| REPO: ${{ github.repository }} | |
| run: | | |
| workflow_path=${GITHUB_WORKFLOW_REF#*/} # 去掉owner | |
| workflow_path=${workflow_path#*/} # 去掉repo名 | |
| workflow_path=${workflow_path%@*} # 去掉@ref | |
| action_file="https://github.com/$REPO/blob/$GITHUB_SHA/$workflow_path" | |
| echo "action_file=$action_file" >> $GITHUB_OUTPUT | |
| - name: Generate GitHub App token | |
| id: app-token | |
| uses: actions/create-github-app-token@v1 | |
| with: | |
| app-id: ${{ vars.DAILY_BOT_APP_ID }} | |
| private-key: ${{ secrets.DAILY_BOT_APP_PRIVATE_KEY }} | |
| - name: Comment on issue | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ steps.app-token.outputs.token }} | |
| script: | | |
| const now = new Date().toLocaleString('zh-CN', { | |
| timeZone: 'Asia/Shanghai', | |
| hour12: false | |
| }); | |
| const actionFile = `${{ steps.resolve-workflow-path.outputs.action_file }}`; | |
| const status = `${{ steps.update-status.outputs.status }}`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: `Set the project status to ${status} based on the \`solving\` label.\n🕒 Time (Beijing, UTC+8): ${now}\n🤖 Triggered by [1problem1day Bot](https://github.com/apps/1problem1day) according to [action file](${actionFile})` | |
| }); |