Set docs to "Ready to Document" when status is Done #470
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: Set docs to "Ready to Document" when status is Done | |
| on: | |
| schedule: | |
| - cron: '0 */2 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| lookback_hours: | |
| description: 'Hours to look back (default: 3)' | |
| required: false | |
| default: '3' | |
| jobs: | |
| update-docs-stage: | |
| runs-on: ubuntu-latest | |
| env: | |
| GH_TOKEN: ${{ secrets.PAT }} | |
| PROJECT_ID: "PVT_kwDODLylHc4A8S01" | |
| DONE_OPTION_ID: "98236657" | |
| DOCUMENTATION_STAGE_FIELD_ID: "PVTSSF_lADODLylHc4A8S01zgxJjRA" | |
| DOCS_NOT_STARTED_OPTION_ID: "36e5dca1" | |
| READY_TO_DOCUMENT_OPTION_ID: "80d991f6" | |
| steps: | |
| - name: Find recently Done items with unstarted docs and update them | |
| env: | |
| LOOKBACK_HOURS: ${{ github.event.inputs.lookback_hours || '3' }} | |
| run: | | |
| # Only process items updated in the lookback window (default 3 hours covers 2-hour cron with buffer) | |
| HOURS="${LOOKBACK_HOURS:-3}" | |
| CUTOFF=$(date -u -d "$HOURS hours ago" '+%Y-%m-%dT%H:%M:%SZ') | |
| echo "Processing items updated after $CUTOFF" | |
| # Fetch all project items with Status and Documentation Stage, paginating | |
| CURSOR="" | |
| ALL_ITEMS="[]" | |
| while true; do | |
| if [ -z "$CURSOR" ]; then | |
| AFTER_ARG="" | |
| else | |
| AFTER_ARG=", after: \"$CURSOR\"" | |
| fi | |
| RESULT=$(gh api graphql -f query=" | |
| query { | |
| node(id: \"$PROJECT_ID\") { | |
| ... on ProjectV2 { | |
| items(first: 100${AFTER_ARG}) { | |
| pageInfo { hasNextPage endCursor } | |
| nodes { | |
| id | |
| updatedAt | |
| status: fieldValueByName(name: \"Status\") { | |
| ... on ProjectV2ItemFieldSingleSelectValue { optionId } | |
| } | |
| docs: fieldValueByName(name: \"Documentation Stage\") { | |
| ... on ProjectV2ItemFieldSingleSelectValue { optionId } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| ") | |
| NODES=$(echo "$RESULT" | jq '.data.node.items.nodes') | |
| ALL_ITEMS=$(echo "$ALL_ITEMS $NODES" | jq -s '.[0] + .[1]') | |
| HAS_NEXT=$(echo "$RESULT" | jq -r '.data.node.items.pageInfo.hasNextPage') | |
| if [ "$HAS_NEXT" != "true" ]; then | |
| break | |
| fi | |
| CURSOR=$(echo "$RESULT" | jq -r '.data.node.items.pageInfo.endCursor') | |
| done | |
| TOTAL=$(echo "$ALL_ITEMS" | jq 'length') | |
| echo "Fetched $TOTAL total project items" | |
| # Filter to recently updated items, then find Status=Done with docs unset/Not Started | |
| ITEMS_TO_UPDATE=$(echo "$ALL_ITEMS" | jq -c --arg cutoff "$CUTOFF" --arg done "$DONE_OPTION_ID" --arg notStarted "$DOCS_NOT_STARTED_OPTION_ID" '[ | |
| .[] | select( | |
| .updatedAt > $cutoff and | |
| .status.optionId == $done and | |
| (.docs == null or .docs.optionId == $notStarted) | |
| ) | |
| ]') | |
| COUNT=$(echo "$ITEMS_TO_UPDATE" | jq 'length') | |
| echo "Found $COUNT items with Status=Done and docs unset or Not Started" | |
| if [ "$COUNT" -eq 0 ]; then | |
| echo "Nothing to update" | |
| exit 0 | |
| fi | |
| # Update each matching item | |
| while read -r ITEM; do | |
| ITEM_ID=$(echo "$ITEM" | jq -r '.id') | |
| echo "Setting Documentation Stage to Ready to Document for item $ITEM_ID" | |
| gh api graphql -f query=" | |
| mutation { | |
| updateProjectV2ItemFieldValue(input: { | |
| projectId: \"$PROJECT_ID\", itemId: \"$ITEM_ID\", | |
| fieldId: \"$DOCUMENTATION_STAGE_FIELD_ID\", | |
| value: { singleSelectOptionId: \"$READY_TO_DOCUMENT_OPTION_ID\" } | |
| }) { projectV2Item { id } } | |
| } | |
| " | |
| done < <(echo "$ITEMS_TO_UPDATE" | jq -c '.[]') |