Bump astro from 5.16.6 to 5.16.9 #14
Workflow file for this run
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
| # .github/workflows/languagetool.yml | |
| name: LanguageTool (PR comment) | |
| on: | |
| pull_request_target: | |
| types: [opened, reopened, synchronize, labeled] | |
| issue_comment: | |
| types: [created] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| concurrency: | |
| group: languagetool-${{ github.event.pull_request.number || github.event.issue.number || github.run_id }} | |
| cancel-in-progress: true | |
| env: | |
| LT_LANGUAGE: en-US | |
| RERUN_LABEL: languagetool:rerun | |
| jobs: | |
| # Comment command -> toggles a label to trigger the PR job | |
| rerun_on_comment: | |
| if: | | |
| github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request && | |
| startsWith(github.event.comment.body, '/languagetool') && | |
| (github.event.comment.author_association == 'MEMBER' || | |
| github.event.comment.author_association == 'OWNER' || | |
| github.event.comment.author_association == 'COLLABORATOR') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Toggle rerun label on PR | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const issue_number = context.issue.number; | |
| const label = process.env.RERUN_LABEL; | |
| // Ensure label exists | |
| try { | |
| await github.rest.issues.getLabel({ owner, repo, name: label }); | |
| } catch { | |
| await github.rest.issues.createLabel({ | |
| owner, repo, name: label, color: '0e8a16', | |
| description: 'Rerun LanguageTool on this PR' | |
| }); | |
| } | |
| // Remove if present (ignore errors), then add to force a new "labeled" event | |
| try { | |
| await github.rest.issues.removeLabel({ owner, repo, issue_number, name: label }); | |
| } catch {} | |
| await github.rest.issues.addLabels({ owner, repo, issue_number, labels: [label] }); | |
| languagetool: | |
| if: | | |
| github.event_name == 'pull_request_target' && | |
| ( | |
| github.event.action == 'opened' || | |
| github.event.action == 'reopened' || | |
| github.event.action == 'synchronize' || | |
| (github.event.action == 'labeled' && github.event.label.name == 'languagetool:rerun') | |
| ) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout PR head (safe) | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ github.event.pull_request.head.repo.full_name }} | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Fetch base SHA for diff | |
| run: | | |
| set -euo pipefail | |
| git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}.git" || true | |
| git fetch --no-tags --depth=1 upstream "${{ github.event.pull_request.base.sha }}" | |
| - name: Setup Java 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: "17" | |
| - name: Download LanguageTool CLI (latest snapshot) | |
| run: | | |
| set -euo pipefail | |
| curl -fsSL -o lt.zip "https://internal1.languagetool.org/snapshots/LanguageTool-latest-snapshot.zip" | |
| rm -rf .lt | |
| mkdir -p .lt | |
| unzip -q lt.zip -d .lt | |
| LT_JAR="$(ls -1 .lt/**/languagetool-commandline.jar 2>/dev/null | head -n1 || true)" | |
| if [ -z "${LT_JAR}" ]; then | |
| echo "Could not find languagetool-commandline.jar in snapshot" >&2 | |
| find .lt -maxdepth 4 -type f -name "*languagetool*jar" -print >&2 || true | |
| exit 1 | |
| fi | |
| echo "LT_JAR=${LT_JAR}" >> "$GITHUB_ENV" | |
| - name: Run LanguageTool + build PR comment (collapsible + exact word) | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| set -euo pipefail | |
| # jq is present on ubuntu-latest, but install if your runner image differs | |
| command -v jq >/dev/null || (sudo apt-get update && sudo apt-get install -y jq) | |
| # Choose files to check | |
| mapfile -t FILES < <(git diff --name-only "$BASE_SHA" "$HEAD_SHA" \ | |
| | grep -E '\.(md|mdx|txt|rst|adoc|asciidoc|tex)$' || true) | |
| # Load custom words (optional) | |
| WORDS_FILE=".languagetool/words.txt" | |
| if [ -f "$WORDS_FILE" ]; then | |
| WORDS_JSON="$(jq -R -s ' | |
| split("\n") | |
| | map(gsub("\r";"")) | |
| | map(select(length>0 and (startswith("#")|not))) | |
| | map(ascii_downcase) | |
| ' "$WORDS_FILE")" | |
| else | |
| WORDS_JSON='[]' | |
| fi | |
| : > results.jsonl | |
| if [ "${#FILES[@]}" -eq 0 ]; then | |
| echo '{"file":"(none)","issues":[]}' >> results.jsonl | |
| else | |
| for f in "${FILES[@]}"; do | |
| [ -f "$f" ] || continue | |
| # LT can print banner lines; keep JSON only (accepts either { or [) | |
| java -jar "$LT_JAR" -l "${LT_LANGUAGE}" --json "$f" 2>/dev/null \ | |
| | sed -n '/^[{[]/,$p' > lt.json || true | |
| # Extract issues and filter spelling-ish matches for custom words | |
| jq -c \ | |
| --arg file "$f" \ | |
| --argjson words "$WORDS_JSON" ' | |
| def bad_raw: | |
| (.context.offset // 0) as $o | |
| | (.context.length // 0) as $l | |
| | (.context.text // "") as $t | |
| | ($t[$o:($o+$l)]); | |
| def badtoken: | |
| (bad_raw | |
| | gsub("^[^[:alnum:]]+|[^[:alnum:]]+$";"") | |
| | ascii_downcase); | |
| (.matches // []) | |
| | map( | |
| . as $m | |
| | ($m.rule.id // "") as $rid | |
| | ($m.rule.category.id // "") as $cat | |
| | (badtoken) as $bt | |
| | select( | |
| ( (( $cat == "TYPOS") or ($rid|test("MORFOLOGIK";"i")) ) | |
| and (($words|index($bt)) != null) | |
| ) | not | |
| ) | |
| | { | |
| message: ($m.message // "LanguageTool finding"), | |
| rule: $rid, | |
| bad: (bad_raw), | |
| replacements: (($m.replacements // []) | map(.value) | .[0:3]), | |
| context: ($m.context.text // ""), | |
| context_offset: ($m.context.offset // 0), | |
| context_length: ($m.context.length // 0) | |
| } | |
| ) | |
| | {file:$file, issues:.} | |
| ' lt.json >> results.jsonl | |
| done | |
| fi | |
| # Build markdown body (stored as a file) - collapsible per file | |
| node <<'NODE' | |
| const fs = require("fs"); | |
| const marker = "<!-- languagetool-report -->"; | |
| const raw = fs.readFileSync("results.jsonl","utf8").trim(); | |
| const lines = raw ? raw.split("\n").filter(Boolean) : []; | |
| const parsed = lines.map(l => JSON.parse(l)); | |
| const checkedFiles = parsed.map(p => p.file).filter(f => f && f !== "(none)"); | |
| const byFile = parsed | |
| .filter(p => Array.isArray(p.issues) && p.issues.length > 0) | |
| .reduce((acc, p) => { acc[p.file] = p.issues; return acc; }, {}); | |
| let total = 0; | |
| for (const f of Object.keys(byFile)) total += byFile[f].length; | |
| function inlineCode(s) { | |
| if (s == null) return ""; | |
| return String(s).replace(/`/g, "\\`").replace(/\n/g, " ").trim(); | |
| } | |
| function shortContext(text, maxLen=220) { | |
| const t = (text || "").replace(/\s+/g, " ").trim(); | |
| if (t.length <= maxLen) return t; | |
| return t.slice(0, maxLen - 1) + "…"; | |
| } | |
| let body = | |
| `${marker} | |
| ## LanguageTool report | |
| **Language:** \`${process.env.LT_LANGUAGE || "en-US"}\` | |
| **Checked files:** ${checkedFiles.length} | |
| **Findings:** ${total} | |
| `; | |
| if (!checkedFiles.length) { | |
| body += `\nNo supported text files changed in this PR (based on configured extensions).\n`; | |
| } else if (total === 0) { | |
| body += `\n✅ No issues found in the changed text files.\n`; | |
| } else { | |
| body += `\n---\n`; | |
| for (const [file, issues] of Object.entries(byFile)) { | |
| body += `\n<details>\n<summary><strong>${file}</strong> — ${issues.length} finding(s)</summary>\n\n`; | |
| for (const it of issues.slice(0, 200)) { | |
| const found = inlineCode(it.bad); | |
| const ctx = shortContext(it.context); | |
| const sug = (it.replacements && it.replacements.length) | |
| ? `Suggested: ${it.replacements.map(s => `\`${inlineCode(s)}\``).join(", ")}\n` | |
| : ""; | |
| body += | |
| `- **${inlineCode(it.rule || "RULE")}**: ${inlineCode(it.message)} | |
| - Found: \`${found}\` | |
| - ${sug ? sug.trimEnd() : "Suggested: (none)"} | |
| - Context: ${ctx ? `> ${ctx}` : "(none)"} | |
| `; | |
| } | |
| if (issues.length > 200) body += `…(${issues.length - 200} more in this file)\n\n`; | |
| body += `</details>\n`; | |
| } | |
| } | |
| fs.writeFileSync("comment.md", body.trim() + "\n"); | |
| NODE | |
| - name: Post or update PR comment | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const issue_number = context.payload.pull_request.number; | |
| const body = fs.readFileSync('comment.md', 'utf8'); | |
| const marker = '<!-- languagetool-report -->'; | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner, repo, issue_number, per_page: 100 | |
| }); | |
| const existing = comments.find(c => (c.body || '').includes(marker)); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| owner, repo, comment_id: existing.id, body | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner, repo, issue_number, body | |
| }); | |
| } | |
| - name: Remove rerun label | |
| if: github.event.action == 'labeled' && github.event.label.name == 'languagetool:rerun' | |
| continue-on-error: true | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| await github.rest.issues.removeLabel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.payload.pull_request.number, | |
| name: process.env.RERUN_LABEL, | |
| }); |