snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-23 16:12:52 +05:00
commit a774ac673a
4541 changed files with 770499 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
#!/bin/bash
# Batch fetch PR details for changelog categorization
#
# Usage: ./fetch-pr-batch.sh <pr1> <pr2> ...
# or: echo "1234 5678" | ./fetch-pr-batch.sh
# Output: JSON array of PR details
set -e
# Collect PR numbers from arguments or stdin
prs=()
if [ $# -gt 0 ]; then
prs=("$@")
else
while read -r line; do
for pr in $line; do
prs+=("$pr")
done
done
fi
if [ ${#prs[@]} -eq 0 ]; then
echo "Usage: $0 <pr1> <pr2> ..." >&2
echo " or: echo '1234 5678' | $0" >&2
exit 1
fi
# Build GraphQL query for batch fetching
# This is much faster than individual gh pr view calls
query='query($owner: String!, $repo: String!) {'
for i in "${!prs[@]}"; do
pr="${prs[$i]}"
query+="
pr$i: repository(owner: \$owner, name: \$repo) {
pullRequest(number: $pr) {
number
title
author { login }
mergedAt
labels(first: 10) { nodes { name } }
body
}
}"
done
query+='}'
# Execute query
result=$(gh api graphql -f query="$query" -f owner="tldraw" -f repo="tldraw" 2>/dev/null)
# Transform into cleaner JSON array
echo "$result" | jq '[.data | to_entries[] | .value.pullRequest | select(. != null) | {
number: .number,
title: .title,
author: .author.login,
merged_at: .mergedAt,
labels: [.labels.nodes[].name],
body: .body
}] | sort_by(.number) | reverse'

View File

@@ -0,0 +1,116 @@
#!/bin/bash
# Get changelog status: versions, whether archival is needed, and the diff branch
#
# Usage: ./get-changelog-status.sh <tldraw-repo-dir>
# Output: JSON with version info and status
#
# Requires a local clone of tldraw/tldraw.
set -e
if [ -z "$1" ]; then
echo "Usage: $0 <tldraw-repo-dir>" >&2
echo "Example: $0 /tmp/tldraw" >&2
exit 1
fi
TLDRAW_REPO="$1"
RELEASES_DIR="$TLDRAW_REPO/apps/docs/content/releases"
NEXT_FILE="$RELEASES_DIR/next.mdx"
# Extract last_version from next.mdx frontmatter (if present)
last_version=""
if [ -f "$NEXT_FILE" ]; then
last_version=$(grep -E "^last_version:" "$NEXT_FILE" 2>/dev/null | sed "s/last_version: *//" | tr -d "'\"\n" || echo "")
fi
# Get the latest published release from GitHub
latest_release=$(gh release list -R tldraw/tldraw --exclude-drafts --limit 1 --json tagName,publishedAt -q '.[0]' 2>/dev/null || echo '{}')
latest_tag=$(echo "$latest_release" | jq -r '.tagName // empty')
latest_date=$(echo "$latest_release" | jq -r '.publishedAt // empty')
# Determine if we need to archive (latest release is newer than last_version)
needs_archive="false"
if [ -n "$latest_tag" ] && [ -n "$last_version" ]; then
if [ "$latest_tag" != "$last_version" ]; then
needs_archive="true"
fi
elif [ -n "$latest_tag" ] && [ -z "$last_version" ]; then
# No last_version set, assume we might need to check
needs_archive="unknown"
fi
# Determine the release branch to diff against
# e.g., v4.3.0 -> v4.3.x, or if latest is v4.3.1 -> v4.3.x
diff_branch=""
if [ -n "$latest_tag" ]; then
# Extract major.minor from tag (v4.3.0 -> 4.3)
version_nums=$(echo "$latest_tag" | sed 's/^v//' | cut -d. -f1,2)
diff_branch="v${version_nums}.x"
fi
# Check if the archive file already exists
archive_exists="false"
if [ -n "$latest_tag" ]; then
archive_file="$RELEASES_DIR/${latest_tag}.mdx"
if [ -f "$archive_file" ]; then
archive_exists="true"
fi
fi
# Check if next.mdx has content (more than just frontmatter)
next_has_content="false"
if [ -f "$NEXT_FILE" ]; then
# Count lines after frontmatter (after second ---)
content_lines=$(awk '/^---$/{c++;next}c==2' "$NEXT_FILE" | grep -v '^[[:space:]]*$' | wc -l | tr -d ' ')
if [ "$content_lines" -gt 0 ]; then
next_has_content="true"
fi
fi
# Determine source based on weeks since the last minor/major release.
# The SDK releases every 4 weeks. During the first 3 weeks (development),
# we gather PRs from main. At 3+ weeks (freeze week), we switch to production.
#
# Find the last minor or major release (skip patches like v4.3.1, v4.3.2)
source="main"
last_minor_date=""
if [ -n "$latest_tag" ]; then
# Get the .0 release for the current minor version (e.g., v4.4.0)
minor_tag=$(echo "$latest_tag" | sed 's/^v//' | cut -d. -f1,2)
minor_release_tag="v${minor_tag}.0"
# Get the publish date of that .0 release
last_minor_date=$(gh release view "$minor_release_tag" -R tldraw/tldraw --json publishedAt -q '.publishedAt' 2>/dev/null || echo "")
if [ -n "$last_minor_date" ]; then
# Calculate weeks since the minor release
release_epoch=$(date -jf "%Y-%m-%dT%H:%M:%SZ" "$last_minor_date" "+%s" 2>/dev/null || date -d "$last_minor_date" "+%s" 2>/dev/null || echo "")
now_epoch=$(date "+%s")
if [ -n "$release_epoch" ]; then
days_since=$(( (now_epoch - release_epoch) / 86400 ))
weeks_since=$(( days_since / 7 ))
if [ "$weeks_since" -ge 3 ]; then
source="production"
fi
fi
fi
fi
# The last tag is the latest release tag (used by get-new-prs-from-main.sh)
last_tag="${latest_tag}"
# Output JSON
cat <<EOF
{
"last_version": "${last_version}",
"latest_release": {
"tag": "${latest_tag}",
"published_at": "${latest_date}"
},
"diff_branch": "${diff_branch}",
"last_tag": "${last_tag}",
"source": "${source}",
"needs_archive": ${needs_archive},
"archive_exists": ${archive_exists},
"next_has_content": ${next_has_content}
}
EOF

View File

@@ -0,0 +1,88 @@
#!/bin/bash
# Find PR numbers on the main branch since a release tag.
# Uses `git cherry` to compare patches between origin/main and the
# release tag, excluding commits that were cherry-picked to production
# and already shipped in the release.
#
# Usage: ./get-new-prs-from-main.sh <tldraw-repo-dir> <release-tag>
# Example: ./get-new-prs-from-main.sh /tmp/tldraw v4.4.0
#
# Output:
# PR numbers (one per line) on stdout, then any commits
# without PR numbers (hash + title) on stderr.
#
# Requires a local clone of tldraw/tldraw.
set -e
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: $0 <tldraw-repo-dir> <release-tag>" >&2
echo "Example: $0 /tmp/tldraw v4.4.0" >&2
exit 1
fi
TLDRAW_REPO="$1"
RELEASE_TAG="$2"
cd "$TLDRAW_REPO"
# Fetch to ensure we have latest refs
git fetch origin main --quiet 2>/dev/null || true
# Verify the tag exists
if ! git rev-parse "$RELEASE_TAG" >/dev/null 2>&1; then
echo "Error: tag '$RELEASE_TAG' not found" >&2
exit 1
fi
# The release tag lives on the production branch, which has a separate
# history from main (deploy commits, hotfixes, version bumps). Many
# commits on main after the branch point were cherry-picked to production
# and shipped in the release. We use `git cherry` to compare patches and
# exclude commits that are already in the release — just like
# get-new-prs.sh does for production.
#
# `git cherry <release-tag> origin/main` marks commits unique to main
# with '+' and those already in the release with '-'.
commit_hashes=$(git cherry "$RELEASE_TAG" origin/main 2>/dev/null \
| grep '^+' \
| cut -d' ' -f2)
pr_numbers=()
unmatched=()
for hash in $commit_hashes; do
# Get the first line of the commit message
title=$(git log -1 --pretty=format:%s "$hash" 2>/dev/null)
# Skip [skip ci] commits (version bumps, deploys)
if echo "$title" | grep -q '\[skip ci\]'; then
continue
fi
# Skip deploy commits
if echo "$title" | grep -q '^Deploy from'; then
continue
fi
# Extract PR number from commit message (format: "... (#1234)")
pr=$(echo "$title" | grep -oE '#[0-9]+' | head -1 | sed 's/#//')
if [ -n "$pr" ]; then
pr_numbers+=("$pr")
else
unmatched+=("$hash $title")
fi
done
# Output unique PR numbers, sorted descending
printf '%s\n' "${pr_numbers[@]}" | sort -rn | uniq
# Output unmatched commits to stderr
if [ ${#unmatched[@]} -gt 0 ]; then
echo "" >&2
echo "Commits without PR numbers:" >&2
for line in "${unmatched[@]}"; do
echo " $line" >&2
done
fi

View File

@@ -0,0 +1,76 @@
#!/bin/bash
# Find PR numbers on the production branch since a release branch.
# Uses `git cherry` (like extract-draft-changelog.tsx) to correctly
# handle cherry-picked hotfix commits.
#
# Usage: ./get-new-prs.sh <tldraw-repo-dir> <release-branch>
# Example: ./get-new-prs.sh /tmp/tldraw v4.2.x
#
# Output:
# PR numbers (one per line), then any commits
# without PR numbers (hash + title) on stderr.
#
# Requires a local clone of tldraw/tldraw.
set -e
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: $0 <tldraw-repo-dir> <release-branch>" >&2
echo "Example: $0 /tmp/tldraw v4.2.x" >&2
exit 1
fi
TLDRAW_REPO="$1"
RELEASE_BRANCH="$2"
cd "$TLDRAW_REPO"
# Fetch to ensure we have latest refs
git fetch origin production "$RELEASE_BRANCH" --quiet 2>/dev/null || true
# Use git cherry to find commits on production that aren't on the
# release branch. git cherry compares patches (not hashes), so it
# correctly handles cherry-picks and hotfixes.
# Lines starting with '+' are unique to production.
commit_hashes=$(git cherry "origin/$RELEASE_BRANCH" origin/production 2>/dev/null \
| grep '^+' \
| cut -d' ' -f2)
pr_numbers=()
unmatched=()
for hash in $commit_hashes; do
# Get the first line of the commit message
title=$(git log -1 --pretty=format:%s "$hash" 2>/dev/null)
# Skip [skip ci] commits (version bumps, deploys)
if echo "$title" | grep -q '\[skip ci\]'; then
continue
fi
# Skip deploy commits
if echo "$title" | grep -q '^Deploy from'; then
continue
fi
# Extract PR number from commit message (format: "... (#1234)")
pr=$(echo "$title" | grep -oE '#[0-9]+' | head -1 | sed 's/#//')
if [ -n "$pr" ]; then
pr_numbers+=("$pr")
else
unmatched+=("$hash $title")
fi
done
# Output unique PR numbers, sorted descending
printf '%s\n' "${pr_numbers[@]}" | sort -rn | uniq
# Output unmatched commits (hotfixes without PR numbers) to stderr
if [ ${#unmatched[@]} -gt 0 ]; then
echo "" >&2
echo "Commits without PR numbers (likely hotfixes):" >&2
for line in "${unmatched[@]}"; do
echo " $line" >&2
done
fi

View File

@@ -0,0 +1,84 @@
#!/bin/bash
# Update (or create) the draft GitHub release for the next release using the
# current next.mdx content. publish-new.ts finds this draft by name (vX.Y.0) and
# publishes its body verbatim at release time, so keeping it in sync with next.mdx
# means the GitHub release and the docs release page always match.
#
# Usage: ./update-draft-release.sh <tldraw-repo-dir> [next-version]
#
# next-version overrides the target tag (with or without a leading `v`). Pass it
# for a major release or any override, so the draft name matches the version
# publish-new.ts will resolve. When omitted, the target defaults to the next
# minor of last_version — the common case.
#
# Requires a local clone of tldraw/tldraw and an authenticated gh CLI.
set -e
if [ -z "$1" ]; then
echo "Usage: $0 <tldraw-repo-dir> [next-version]" >&2
echo "Example: $0 /tmp/tldraw # minor bump of last_version" >&2
echo "Example: $0 /tmp/tldraw v6.0.0 # explicit target (major/override)" >&2
exit 1
fi
TLDRAW_REPO="$1"
NEXT_FILE="$TLDRAW_REPO/apps/docs/content/releases/next.mdx"
if [ ! -f "$NEXT_FILE" ]; then
echo "next.mdx not found at $NEXT_FILE" >&2
exit 1
fi
if [ -n "$2" ]; then
# Explicit target — normalize to a leading `v`. Use this for major releases or
# overrides, where publish-new.ts resolves the next version from NPM rather than
# a minor bump (e.g. --bump major -> v6.0.0).
next_tag="v$(echo "$2" | sed 's/^v//')"
else
# The draft tracks the next minor release. Derive it from last_version (the most
# recent published release recorded in next.mdx frontmatter): bump minor, patch 0.
# e.g. last_version v5.2.0 -> draft v5.3.0.
last_version=$(grep -E "^last_version:" "$NEXT_FILE" | head -1 | sed "s/last_version: *//" | tr -d "'\"[:space:]")
if [ -z "$last_version" ]; then
echo "Could not read last_version from $NEXT_FILE" >&2
exit 1
fi
major=$(echo "$last_version" | sed 's/^v//' | cut -d. -f1)
minor=$(echo "$last_version" | sed 's/^v//' | cut -d. -f2)
next_tag="v${major}.$((minor + 1)).0"
fi
# Body = next.mdx with the frontmatter block stripped (everything after the second ---).
body_file=$(mktemp)
awk 'f{print} /^---$/{c++; if(c==2){f=1}}' "$NEXT_FILE" > "$body_file"
# Fail loudly if there is nothing to publish rather than pushing an empty draft.
if ! grep -qE '[^[:space:]]' "$body_file"; then
echo "next.mdx has no content below the frontmatter; refusing to write an empty draft." >&2
rm -f "$body_file"
exit 1
fi
echo "Draft release target: $next_tag" >&2
# Look up an existing release for this tag (finds drafts too).
existing=$(gh release view "$next_tag" -R tldraw/tldraw --json isDraft 2>/dev/null || echo "")
if [ -n "$existing" ]; then
is_draft=$(echo "$existing" | jq -r '.isDraft')
if [ "$is_draft" != "true" ]; then
echo "Release $next_tag already exists and is published; refusing to edit." >&2
rm -f "$body_file"
exit 1
fi
echo "Updating existing draft release $next_tag" >&2
gh release edit "$next_tag" -R tldraw/tldraw --title "$next_tag" --notes-file "$body_file"
else
echo "Creating new draft release $next_tag" >&2
gh release create "$next_tag" -R tldraw/tldraw --draft --title "$next_tag" --notes-file "$body_file"
fi
rm -f "$body_file"
echo "Done. Draft release $next_tag is in sync with next.mdx." >&2