Skip to content

Commit ae3f904

Browse files
committed
Merge branch 'upstream-development'
2 parents 00be243 + 6aa2179 commit ae3f904

40 files changed

Lines changed: 1484 additions & 111 deletions

.github/skills/update-git/SKILL.md

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
---
2+
name: update-git
3+
description: Walk through updating the version of Git shipped in GitHub Desktop. This is a multi-repo process spanning dugite-native, dugite, and desktop. Use this when asked to update Git, update Git for Windows, or bump the Git version.
4+
---
5+
6+
# Update Git Version in GitHub Desktop
7+
8+
This skill guides the user through updating the version of Git that GitHub
9+
Desktop ships. This is a multi-repo cascade:
10+
11+
1. **desktop/dugite-native** — bundles Git binaries for each platform
12+
2. **desktop/dugite** — Node.js wrapper that consumes dugite-native releases
13+
3. **desktop/desktop** — the app itself, consumes dugite as an npm dependency
14+
15+
Each step must complete (PR merged + release published) before the next can
16+
begin.
17+
18+
## Information to Gather
19+
20+
Before starting, use `<skill-directory>/check-versions.sh` to show the user
21+
what's currently shipped and what's available. Then ask the user which
22+
components they want to update.
23+
24+
Even if the user only asks about one component (e.g., Git for Windows),
25+
**proactively check all components** and recommend bundling any other available
26+
updates. This avoids having to reship dugite-native if a test fails due to a
27+
version mismatch in a component the user didn't update.
28+
29+
Gather the following:
30+
31+
- **Git version** (e.g., `v2.48.0`) — or `latest`
32+
- **Git for Windows version** (e.g., `v2.48.0.windows.1`) — or `latest`
33+
- **Git LFS version** — or `skip` if not updating (default: `skip`)
34+
- **Git Credential Manager version** — or `skip` if not updating (default:
35+
`skip`)
36+
37+
## Step 1: Update Dependencies in dugite-native
38+
39+
Use the helper script to trigger the workflow:
40+
41+
```bash
42+
bash <skill-directory>/trigger-workflow.sh dugite-native update-dependencies \
43+
git=<GIT_VERSION> g4w=<G4W_VERSION> lfs=<LFS_VERSION> gcm=<GCM_VERSION>
44+
```
45+
46+
This triggers the **Update dependencies** workflow in `desktop/dugite-native`
47+
which will:
48+
49+
- Update `dependencies.json` with new URLs and checksums
50+
- Update the git submodule
51+
- Automatically create a PR
52+
53+
**Important**: The Git and Git for Windows updates are handled by the same
54+
workflow step. If you only want to update Git for Windows, you must still pass
55+
the current Git version (not `skip`) for the `git` input, otherwise the step
56+
will be skipped entirely. Use `<skill-directory>/check-versions.sh` to find the
57+
current Git version and pass it as the `git` input. For example, if Git is
58+
currently at `v2.53.0` and you only want to update GfW:
59+
60+
```bash
61+
bash <skill-directory>/trigger-workflow.sh dugite-native update-dependencies \
62+
git=v2.53.0 g4w=v2.53.0.windows.2 lfs=skip gcm=skip
63+
```
64+
65+
Tell the user to:
66+
67+
1. Wait for the workflow to complete — use the script to check status:
68+
```bash
69+
bash <skill-directory>/check-workflow.sh dugite-native
70+
```
71+
2. When the PR is created, open it in the browser and enable auto-merge:
72+
```bash
73+
bash <skill-directory>/open-pr.sh dugite-native
74+
gh pr merge --auto --squash <PR_NUMBER> --repo desktop/dugite-native
75+
```
76+
Tell the user: "I've enabled auto-merge — please review the PR before CI
77+
finishes so it can merge automatically."
78+
79+
**Do not proceed to Step 2 until the PR is merged.**
80+
81+
## Step 2: Publish a dugite-native Release
82+
83+
Use the helper script to trigger the release workflow:
84+
85+
```bash
86+
bash <skill-directory>/trigger-workflow.sh dugite-native release \
87+
version=<VERSION_TAG> draft=false prerelease=false dry-run=true
88+
```
89+
90+
Suggest running with `dry-run=true` first. If it succeeds, re-run with
91+
`dry-run=false`.
92+
93+
The version tag should follow Git's versioning scheme:
94+
95+
- `v2.48.0` for a new Git version
96+
- `v2.48.0-1` if only packaging or other dependencies changed
97+
98+
Tell the user to:
99+
100+
1. Wait for the build to complete across all platforms
101+
2. Review the draft release notes — remove infrastructure-only changes
102+
3. Click **Publish** on the GitHub release page
103+
104+
Use this to check if the release exists:
105+
106+
```bash
107+
bash <skill-directory>/check-release.sh dugite-native <VERSION_TAG>
108+
```
109+
110+
**Do not proceed to Step 3 until the release is published.**
111+
112+
## Step 3: Update dugite-native Version in dugite
113+
114+
Trigger the **Update Git** workflow:
115+
116+
```bash
117+
bash <skill-directory>/trigger-workflow.sh dugite update-git
118+
```
119+
120+
No inputs are needed — it automatically fetches the latest dugite-native release.
121+
122+
The workflow creates a PR that updates `script/embedded-git.json`. Tell the user
123+
to:
124+
125+
1. Wait for the workflow to complete
126+
2. When the PR is created, open it in the browser and enable auto-merge:
127+
```bash
128+
bash <skill-directory>/open-pr.sh dugite
129+
gh pr merge --auto --squash <PR_NUMBER> --repo desktop/dugite
130+
```
131+
Tell the user: "I've enabled auto-merge — please review the PR before CI
132+
finishes so it can merge automatically."
133+
134+
**Do not proceed to Step 4 until the PR is merged.**
135+
136+
## Step 4: Publish dugite to npm
137+
138+
Trigger the **Publish** workflow:
139+
140+
```bash
141+
bash <skill-directory>/trigger-workflow.sh dugite publish \
142+
version=<SEMVER_BUMP> tag=latest dry-run=true
143+
```
144+
145+
- **version**: `minor` for a new Git version, `patch` for bugfix-only
146+
- **tag**: `latest` for stable, `next` for pre-releases
147+
148+
Suggest running with `dry-run=true` first, then `dry-run=false`.
149+
150+
Verify the package was published:
151+
152+
```bash
153+
bash <skill-directory>/check-npm.sh dugite
154+
```
155+
156+
**Do not proceed to Step 5 until the npm package is published.**
157+
158+
## Step 5: Update dugite in desktop
159+
160+
Before proceeding, ask the user what they want to do with the dugite update:
161+
162+
1. **Just bump dugite** — create a PR with the version update on its own
163+
2. **Prepare a production release** — include the dugite bump in a new
164+
production release (e.g., building on an existing beta tag)
165+
3. **Prepare a beta release** — include the dugite bump in a new beta release
166+
off the development branch
167+
168+
### Option A: Just bump dugite (standalone PR)
169+
170+
**Important**: Desktop has a nested package structure. The dugite dependency
171+
lives in `app/package.json`, not the root `package.json`. Do NOT run
172+
`yarn upgrade dugite` from the repo root — it will add dugite to the wrong
173+
package.json.
174+
175+
```bash
176+
cd <desktop-repo-path>
177+
git checkout development && git pull
178+
git checkout -b update-dugite-<NEW_VERSION>
179+
# Edit app/package.json to set dugite to "^<NEW_VERSION>"
180+
cd app && yarn install && cd ..
181+
yarn why dugite
182+
git add app/package.json app/yarn.lock
183+
git commit -m "Update dugite to <NEW_VERSION>"
184+
git push origin HEAD
185+
gh pr create --title "Update dugite to <NEW_VERSION> (Git <GIT_VERSION>)" \
186+
--base development --draft
187+
```
188+
189+
### Option B: Prepare a production release with the dugite bump
190+
191+
If the user wants to cut a production release (e.g., from an existing beta tag
192+
like `release-3.5.6-beta1`):
193+
194+
1. **Check out the latest beta tag** — production releases are based on the
195+
beta, not on `development`:
196+
```bash
197+
cd <desktop-repo-path>
198+
git fetch --tags
199+
git tag --sort=-v:refname | grep "release-.*-beta" | head -1
200+
git checkout <latest-beta-tag>
201+
```
202+
2. Draft the production release:
203+
```bash
204+
yarn draft-release production
205+
```
206+
This will:
207+
- Determine the next production version
208+
- Create a `releases/<version>` branch from the beta tag
209+
- Bump `app/package.json`
210+
- Generate changelog entries from commits since the last release
211+
3. On the release branch, bump dugite by editing `app/package.json` directly
212+
(see note below about the nested package structure):
213+
```bash
214+
# Edit app/package.json to set dugite to "^<NEW_VERSION>"
215+
cd app && yarn install && cd ..
216+
```
217+
4. Review the generated changelog — ensure the dugite/Git update is mentioned
218+
(e.g., `[Improved] Update Git for Windows to <GFW_VERSION>`) and that
219+
version numbers reflect what's actually in this release, not what was in the
220+
beta
221+
5. Commit all changes:
222+
```bash
223+
git add app/package.json app/yarn.lock changelog.json
224+
git commit -m "Bump version and add changelog"
225+
```
226+
6. Push the branch — GitHub Actions will automatically create a release PR
227+
7. Review the release PR — check the changelog and version bump look correct
228+
8. Get the PR reviewed and merge it
229+
9. Verify CI builds pass on the merge commit
230+
231+
If building from a specific tag, ask the user which tag or branch they're basing
232+
the release on.
233+
234+
### Option C: Prepare a beta release with the dugite bump
235+
236+
1. Bump dugite on the development branch and merge it:
237+
```bash
238+
git checkout development && git pull
239+
git checkout -b update-dugite-<NEW_VERSION>
240+
# Edit app/package.json to set dugite to "^<NEW_VERSION>"
241+
cd app && yarn install && cd ..
242+
git add app/package.json app/yarn.lock
243+
git commit -m "Update dugite to <NEW_VERSION>"
244+
git push origin HEAD
245+
gh pr create --title "Update dugite to <NEW_VERSION> (Git <GIT_VERSION>)" \
246+
--base development
247+
```
248+
Merge the PR once CI passes.
249+
2. Then draft the beta release:
250+
```bash
251+
yarn draft-release beta
252+
```
253+
This will:
254+
- Determine the next beta version (incrementing beta number or starting a
255+
new beta series)
256+
- Create a `releases/<version>` branch
257+
- Bump `app/package.json`
258+
- Generate changelog entries
259+
3. Push the branch — GitHub Actions will create a release PR
260+
4. Review the release PR — check the changelog and version bump look correct
261+
5. Get the PR reviewed and merge it
262+
6. Verify CI builds pass on the merge commit
263+
264+
### Combining production + beta releases
265+
266+
A common pattern is to release production first, then immediately cut a beta
267+
that includes the same changes on the development branch. If the user mentions
268+
this, walk them through both in sequence:
269+
270+
1. Draft and release production with the dugite bump on the release branch
271+
(Option B) — when the release PR merges, development gets the dugite bump
272+
2. Draft and release beta off development (Option C, skipping the dugite bump
273+
since it's already on development from the production merge)
274+
275+
## Guidance Style
276+
277+
- Walk through **one step at a time** — don't dump all steps at once
278+
- After explaining each step, ask the user to confirm when it's done before
279+
moving on
280+
- When a workflow creates a PR, open it in the user's browser immediately:
281+
```bash
282+
bash <skill-directory>/open-pr.sh <repo>
283+
```
284+
- **After triggering any workflow**, automatically poll for completion every
285+
15–20 seconds using `check-workflow.sh` and give the user a brief status
286+
update each time (e.g., "Still running — 45s elapsed, Linux arm64 building").
287+
Do not wait for the user to ask — keep polling until the workflow completes
288+
or fails. When checking individual job status, use:
289+
```bash
290+
gh run view <RUN_ID> --repo desktop/<REPO> --json status,jobs \
291+
--jq '.jobs[] | select(.status != "completed") | "\(.name): \(.status)"'
292+
```
293+
- When a workflow creates a PR, immediately open it in the browser and check
294+
for CI status
295+
- If something goes wrong, help troubleshoot before continuing
296+
- Use the helper scripts to check status and trigger workflows rather than
297+
asking the user to navigate to GitHub manually
298+
- Provide direct links to workflow runs and PRs when available
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env bash
2+
# Check the latest published version of a package on npm.
3+
#
4+
# Usage:
5+
# check-npm.sh <package-name>
6+
#
7+
# Examples:
8+
# check-npm.sh dugite
9+
10+
set -euo pipefail
11+
12+
if [ $# -lt 1 ]; then
13+
echo "Usage: check-npm.sh <package-name>"
14+
exit 1
15+
fi
16+
17+
PACKAGE="$1"
18+
19+
echo "=== npm package: ${PACKAGE} ==="
20+
echo ""
21+
22+
echo "Latest version (latest tag):"
23+
npm view "${PACKAGE}" dist-tags.latest 2>/dev/null || echo " (could not fetch)"
24+
25+
echo ""
26+
echo "All dist-tags:"
27+
npm view "${PACKAGE}" dist-tags --json 2>/dev/null || echo " (could not fetch)"
28+
29+
echo ""
30+
echo "Recent versions:"
31+
npm view "${PACKAGE}" versions --json 2>/dev/null | tail -10 || echo " (could not fetch)"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env bash
2+
# Check if a specific release exists in a desktop/* repository.
3+
#
4+
# Usage:
5+
# check-release.sh <repo> <version-tag>
6+
#
7+
# Examples:
8+
# check-release.sh dugite-native v2.48.0
9+
# check-release.sh dugite v3.1.0
10+
11+
set -euo pipefail
12+
13+
if [ $# -lt 2 ]; then
14+
echo "Usage: check-release.sh <repo> <version-tag>"
15+
exit 1
16+
fi
17+
18+
REPO="$1"
19+
TAG="$2"
20+
FULL_REPO="desktop/${REPO}"
21+
22+
echo "Checking for release ${TAG} in ${FULL_REPO}..."
23+
echo ""
24+
25+
if gh release view "${TAG}" --repo "${FULL_REPO}" --json tagName,isDraft,isPrerelease,publishedAt,url 2>/dev/null; then
26+
echo ""
27+
echo "✅ Release ${TAG} exists!"
28+
else
29+
echo "❌ Release ${TAG} not found in ${FULL_REPO}."
30+
echo ""
31+
echo "Latest release:"
32+
gh release view --repo "${FULL_REPO}" --json tagName,publishedAt,url --jq '" \(.tagName) (published \(.publishedAt | split("T")[0]))\n \(.url)"' 2>/dev/null || echo " (no releases found)"
33+
fi
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
# Check the latest available versions of Git, Git for Windows, Git LFS, and
3+
# Git Credential Manager from their GitHub repositories.
4+
5+
set -euo pipefail
6+
7+
echo "=== Latest Available Versions ==="
8+
echo ""
9+
10+
echo "Git (git/git):"
11+
gh api repos/git/git/tags --jq '.[0].name' 2>/dev/null | xargs -I{} echo " {}" || echo " (could not fetch)"
12+
13+
echo ""
14+
echo "Git for Windows (git-for-windows/git):"
15+
gh release view --repo git-for-windows/git --json tagName,publishedAt --jq '" \(.tagName) (released \(.publishedAt | split("T")[0]))"' 2>/dev/null || echo " (could not fetch)"
16+
17+
echo ""
18+
echo "Git LFS (git-lfs/git-lfs):"
19+
gh release view --repo git-lfs/git-lfs --json tagName,publishedAt --jq '" \(.tagName) (released \(.publishedAt | split("T")[0]))"' 2>/dev/null || echo " (could not fetch)"
20+
21+
echo ""
22+
echo "Git Credential Manager (git-ecosystem/git-credential-manager):"
23+
gh release view --repo git-ecosystem/git-credential-manager --json tagName,publishedAt --jq '" \(.tagName) (released \(.publishedAt | split("T")[0]))"' 2>/dev/null || echo " (could not fetch)"
24+
25+
echo ""
26+
echo "=== Currently Shipped in dugite-native ==="
27+
gh release view --repo desktop/dugite-native --json tagName,publishedAt,body --jq '" Release: \(.tagName) (published \(.publishedAt | split("T")[0]))"' 2>/dev/null || echo " (could not fetch)"

0 commit comments

Comments
 (0)