Documentation Freshness Check #41
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: Documentation Freshness Check | |
| on: | |
| schedule: | |
| - cron: '0 0 * * 0' | |
| workflow_dispatch: | |
| jobs: | |
| check_freshness: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v3 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.x' | |
| - name: Create scripts directory | |
| run: mkdir -p .github/scripts | |
| - name: Copy Python script | |
| run: | | |
| cat > .github/scripts/check_freshness.py << 'EOL' | |
| import os | |
| import subprocess | |
| from datetime import datetime, timedelta | |
| FRESHNESS_PERIOD = timedelta(days=180) | |
| IGNORED_FILES = ["_index.md", "support.md"] | |
| now = datetime.now() | |
| def get_last_modified_time(file_path): | |
| result = subprocess.run( | |
| ['git', 'log', '-1', '--format=%ct', file_path], | |
| stdout=subprocess.PIPE, | |
| text=True | |
| ) | |
| timestamp = int(result.stdout.strip()) | |
| return datetime.fromtimestamp(timestamp) | |
| def check_freshness(directory): | |
| stale_files = [] | |
| for root, _, files in os.walk(directory): | |
| for file in files: | |
| if file.endswith(".md"): | |
| relative_path = os.path.relpath(os.path.join(root, file), start=directory) | |
| if file in IGNORED_FILES: | |
| continue | |
| last_modified = get_last_modified_time(os.path.join(root, file)) | |
| time_diff = now - last_modified | |
| if time_diff > FRESHNESS_PERIOD: | |
| stale_files.append((relative_path, last_modified)) | |
| return stale_files | |
| docs_directory = "content" | |
| stale_docs = check_freshness(docs_directory) | |
| sorted_stale_docs = sorted(stale_docs, key=lambda x: x[1]) | |
| if sorted_stale_docs: | |
| with open("stale_docs.txt", "w") as f: | |
| for doc, mod_time in sorted_stale_docs: | |
| f.write(f"- *{doc}* (Last Modified: {mod_time.strftime('%Y-%m-%d')})\n") | |
| else: | |
| with open("stale_docs.txt", "w") as f: | |
| f.write("All documents are fresh!\n") | |
| EOL | |
| - name: Run freshness check | |
| id: check | |
| run: | | |
| python3 .github/scripts/check_freshness.py | |
| if [ -s stale_docs.txt ]; then | |
| echo "HAS_STALE=true" >> $GITHUB_ENV | |
| else | |
| echo "HAS_STALE=false" >> $GITHUB_ENV | |
| fi | |
| - name: Read stale docs output | |
| if: env.HAS_STALE == 'true' | |
| id: read_stale_docs | |
| run: | | |
| thread_message=$(cat stale_docs.txt | sed ':a;N;$!ba;s/\n/\\n/g') | |
| echo "THREAD_MESSAGE=${thread_message}" >> $GITHUB_ENV | |
| - name: Post initial Slack message | |
| id: slack_message | |
| run: | | |
| RESPONSE=$(curl -X POST -H "Authorization: Bearer ${{ secrets.SLACK_BOT_TOKEN }}" \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "channel": "${{ secrets.SLACK_CHANNEL_ID }}", | |
| "text": "📌 *Documentation Freshness Check Results*" | |
| }' \ | |
| https://slack.com/api/chat.postMessage) | |
| echo "$RESPONSE" > slack_response.json | |
| cat slack_response.json # Debugging: print the response | |
| THREAD_TS=$(echo "$RESPONSE" | jq -r '.ts') | |
| if [ -z "$THREAD_TS" ] || [ "$THREAD_TS" == "null" ]; then | |
| echo "Error: Failed to retrieve Slack thread timestamp." | |
| exit 1 | |
| fi | |
| echo "THREAD_TS=$THREAD_TS" >> $GITHUB_ENV | |
| echo "Extracted thread_ts: $THREAD_TS" | |
| - name: Post thread reply with formatted list | |
| if: env.HAS_STALE == 'true' | |
| run: | | |
| curl -X POST -H "Authorization: Bearer ${{ secrets.SLACK_BOT_TOKEN }}" \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "channel": "${{ secrets.SLACK_CHANNEL_ID }}", | |
| "thread_ts": "'"${{ env.THREAD_TS }}"'", | |
| "text": ":warning: *The following docs have not been modified for at least 6 months:*\n\n${{ env.THREAD_MESSAGE }}" | |
| }' \ | |
| https://slack.com/api/chat.postMessage |