Update cloud-feedback.md #13
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: Normalize GitBook assets for Git it Write | |
| on: | |
| push: | |
| branches: [ main ] | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: normalize-assets-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| normalize: | |
| if: ${{ github.actor != 'github-actions[bot]' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Configure author | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Update to latest main (rebase) | |
| run: | | |
| git fetch origin main | |
| git checkout main | |
| git rebase origin/main | |
| - name: Ensure _images exists (flat) | |
| run: mkdir -p _images | |
| # FLATTEN: copy every file under .gitbook/assets into _images (no folders). | |
| # If two files share the same basename, the last one wins (warns). | |
| - name: Copy from .gitbook/assets → _images (flat) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [ -d ".gitbook/assets" ]; then | |
| mapfile -d '' files < <(find .gitbook/assets -type f -print0) | |
| if ((${#files[@]})); then | |
| declare -A seen | |
| dups=0 | |
| for src in "${files[@]}"; do | |
| base="$(basename "$src")" | |
| if [[ -n "${seen[$base]:-}" ]]; then | |
| echo "::warning::Duplicate filename '$base' from '$src' and '${seen[$base]}' — keeping the last copy." >&2 | |
| dups=1 | |
| fi | |
| seen[$base]="$src" | |
| cp -f "$src" "_images/$base" | |
| done | |
| if ((dups)); then | |
| echo "::notice::Consider deduplicating basenames in .gitbook/assets to avoid overwrites." | |
| fi | |
| fi | |
| fi | |
| # REWRITE: turn any .../.gitbook/assets/... or relative _images links into /_images/filename | |
| # and percent-encode spaces/() in the URL target. | |
| - name: Rewrite links to /_images for Git it Write (Python) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| python3 - <<'PY' | |
| import re, glob, os | |
| def enc(path: str) -> str: | |
| return path.replace(' ', '%20').replace('(', '%28').replace(')', '%29') | |
| patterns = ["**/*.md","**/*.MD","**/*.mdx","**/*.MDX","**/*.markdown","**/*.MARKDOWN"] | |
| files = [] | |
| for p in patterns: | |
| files.extend(glob.glob(p, recursive=True)) | |
| for path in files: | |
| with open(path, "r", encoding="utf-8") as f: | |
| s = f.read() | |
| orig = s | |
| # 1) Replace any '/.gitbook/assets/<name>' (in links, src, refs, GitHub raw URLs, etc.) | |
| s = s.replace("/.gitbook/assets/", "/_images/") | |
| # 2) Normalize any relative _images → /_images | |
| s = re.sub(r"\]\(\s*<?(?:\.\./)+_images/", "](/_images/", s) | |
| s = re.sub(r"\]\(\s*<?_images/", "](/_images/", s) | |
| s = re.sub(r'\bsrc\s*=\s*"(?:\.\./)+_images/', 'src="/_images/', s) | |
| s = re.sub(r'\bsrc\s*=\s*"_images/', 'src="/_images/', s) | |
| s = re.sub(r"\bsrc\s*=\s*'(?:\.\./)+_images/", "src='/_images/", s) | |
| s = re.sub(r"\bsrc\s*=\s*'_images/", "src='/_images/", s) | |
| s = re.sub(r'(?im)^(\[[^\]]+\]:\s*)(?:\.\./)+_images/', r"\1/_images/", s) | |
| s = re.sub(r'(?im)^(\[[^\]]+\]:\s*)_images/', r"\1/_images/", s) | |
| # 3) Percent-encode spaces/() in targets that point to /_images/... | |
| # a) inline MD links: ](/_images/xxx...) keep any title after a space | |
| def enc_inline(m): | |
| url = m.group(1) | |
| return "](" + enc(url) | |
| s = re.sub(r"\]\((/_images/[^\s\)]*)", enc_inline, s) | |
| # b) HTML src="...": double & single quotes | |
| def enc_src_dq(m): | |
| return 'src="' + enc(m.group(1)) + '"' | |
| s = re.sub(r'src="(/_images/[^"]*)"', enc_src_dq, s) | |
| def enc_src_sq(m): | |
| return "src='" + enc(m.group(1)) + "'" | |
| s = re.sub(r"src='(/_images/[^']*)'", enc_src_sq, s) | |
| # c) reference-style: [id]: /_images/xxx (keep trailing title) | |
| def enc_ref(m): | |
| return m.group(1) + enc(m.group(2)) + m.group(3) | |
| s = re.sub(r'(?im)^(\[[^\]]+\]:\s*)(/_images/\S+)(.*)$', enc_ref, s) | |
| if s != orig: | |
| with open(path, "w", encoding="utf-8") as f: | |
| f.write(s) | |
| print(f"Rewrote: {path}") | |
| PY | |
| - name: Commit changes (if any) | |
| run: | | |
| if [ -n "$(git status --porcelain)" ]; then | |
| git add -A | |
| git commit -m "Normalize images to /_images/* and rewrite links [ci skip]" | |
| else | |
| echo "No changes to commit." | |
| fi | |
| - name: Rebase on latest and push (retry with --force-with-lease) | |
| shell: bash | |
| run: | | |
| if [ -z "$(git log origin/main..HEAD)" ]; then | |
| echo "No new commits to push." | |
| exit 0 | |
| fi | |
| for attempt in 1 2 3; do | |
| echo "Push attempt $attempt..." | |
| if git push --force-with-lease; then | |
| echo "Pushed successfully." | |
| exit 0 | |
| fi | |
| echo "Push rejected. Fetching and rebasing..." | |
| git fetch origin main | |
| git rebase origin/main || exit 1 | |
| sleep 2 | |
| done | |
| echo "Giving up after 3 attempts." | |
| exit 1 |