Skip to content

Commit e02b146

Browse files
authored
Merge branch 'main' into feat/tls-ui-api-server
2 parents e21f104 + ad58c5a commit e02b146

2 files changed

Lines changed: 133 additions & 0 deletions

File tree

CONTRIBUTING.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ docs: update testing guide with Vitest examples
149149
test: add fuzz tests for repo name validation
150150
```
151151

152+
### Release and Branching Process
153+
154+
To understand when your contribution will get merged upstream and published to NPM, see our [Releases guide](./docs/Releases.md).
155+
152156
## Testing
153157

154158
GitProxy has three test suites, each serving a different purpose.

docs/Releases.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# GitProxy Releases
2+
3+
GitProxy has a standardized release process to ensure they are done in a timely manner, and to prevent extensive merge conflicts. We encourage contributors to read this before opening a PR.
4+
5+
## Branching Strategy
6+
7+
GitProxy follows a [GitLabFlow branching strategy](https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/) with **cascade-based merging** for bugfixes as opposed to cherry-picking. [This blogpost](https://blog.joshuins.com/implementing-cascading-merges-in-github-actions-part-1-99a907e566f3) explains in more detail how cascade-based merging works. See this [StackExchange discussion](https://softwareengineering.stackexchange.com/questions/460758/is-cascade-merging-forward-porting-riskier-than-backporting) for pros and cons of cascade-based merging.
8+
9+
There are two types of long-lived branches in GitProxy: `main`, and release branches named `release/X.Y` (example: `release/2.1`). The `main` branch is where we integrate any new PRs. Every feature, refactor, dependency bump, documentation improvement, etc., is opened as a PR against `main`.
10+
11+
When a milestone reaches completion, we cut a `release/X.Y` branch from `main`, and from that point **the branch's scope is frozen**. Only bugfixes are allowed into the release branch.
12+
13+
When a bug affecting a released version is reported, we **open a PR against the oldest supported release branch containing the bug**. After the fix is merged to that branch, we **merge it forward**. Suppose we support the following versions: `1.1`, `2.2` and `3.0`. If a bug affecting `2.2` is discovered, we first merge the fix into `2.2`. Then, we merge `2.2` into `3.0`, which ensures that all affected, supported versions inherit the bugfix. Since commit identity is preserved, a single SHA exists on all branches the fix was applied to. We can then easily audit that a particular version contains a fix by using `git merge-base --is-ancestor`.
14+
15+
Features and changes other than bugfixes never go into a release branch. If you want a feature included in the next minor release, you should target `main` so it gets picked up in the next milestone.
16+
17+
## Release Planning
18+
19+
GitProxy uses [GitHub milestones](https://github.com/finos/git-proxy/milestones) to plan minor and major releases. Milestones have a fixed scope and a target deadline which we agree upon during our fortnightly [Community Meeting](https://github.com/finos/git-proxy#contact). The deadline serves as the intended release date, and allows GitProxy to keep a predictable cadence.
20+
21+
Historically, GitProxy has had [trouble with scope creep](https://github.com/finos/git-proxy/discussions/1442) delaying releases. To remediate this, new features are added to future milestones rather than existing ones, save for rare exceptions. When every issue in a milestone is closed, we create the corresponding `release/X.Y` branch from `main` and the scope is officially frozen.
22+
23+
Patch releases, on the other hand, are excluded from milestone planning as they follow the cascade-merge process described earlier. This means we can ship fixes as soon as they're completed regardless of the planning cycle.
24+
25+
## Versioning
26+
27+
GitProxy follows [Semantic Versioning](https://semver.org/):
28+
29+
- Breaking changes: bump the major version (`1.4.5` bumps to `2.0.0`)
30+
- Backward-compatible features: bump the minor version (`1.4.5` bumps to `1.5.0`)
31+
- Bugfixes, maintenance, documentation, etc.: bump the patch version (`1.4.5` bumps to `1.4.6`)
32+
33+
Version bumps are computed automatically by our release drafter workflow, based on this [configuration file](https://github.com/finos/git-proxy/blob/main/.github/release-drafter-config.yml). Thus, we encourage contributors to label their PRs and commits appropriately as described below.
34+
35+
## Pull Request Conventions
36+
37+
Both release notes and the release drafter workflow rely on [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/)-style PR titles for automatic tagging.
38+
39+
- `feat:` labels the PR as a feature (minor bump)
40+
- `fix:` labels the PR as a bugfix (patch bump)
41+
- `break:` labels the PR as a breaking change (major bump)
42+
- Adding an exclamation mark (ex: `feat!:`) also labels the PR as a breaking change (major bump)
43+
- Other prefixes map to the maintenance categories defined in `release-drafter.yml`
44+
45+
Release notes use PR titles directly. They should be written as user-facing changelog entries, in other words: in present tense, descriptive, and free of administrative references (meetings, etc.) or jargon.
46+
47+
- **Good:** fix: handle crashing on empty proxy config
48+
- **Not good:** fix: bug from last community call
49+
50+
Keep in mind that maintainers may adjust the labels manually if appropriate.
51+
52+
## Release Process
53+
54+
The actual release process is largely automated via two GitHub Actions workflows: [`release-drafter.yml`](https://github.com/finos/git-proxy/blob/main/.github/workflows/release-drafter.yml) and [`npm.yml`](https://github.com/finos/git-proxy/blob/main/.github/workflows/npm.yml).
55+
56+
### Release Drafter
57+
58+
This workflow runs whenever:
59+
60+
1. You create a `release/*` branch from `main`
61+
2. You push to an existing `release/*` branch
62+
63+
It generates a draft GitHub Release, which is kept up-to-date with a categorised changelog and the right version number. The release drafter action can be customized in [release-drafter-config.yml](https://github.com/finos/git-proxy/blob/main/.github/release-drafter-config.yml).
64+
65+
When a release is ready to ship, a maintainer:
66+
67+
1. Reviews the draft for the relevant `release/*` branch
68+
2. Edits the release notes if necessary (for instance, adding a migration guide for breaking changes)
69+
3. Clicks Publish.
70+
71+
Publishing creates a git tag, and triggers the `npm.yml` workflow described below.
72+
73+
### Publish to NPM
74+
75+
This workflow runs whenever you publish a GitHub release. As of writing, we don't have any [automation for bumping the versions](https://github.com/finos/git-proxy/issues/1533) in `/package.json` and `/packages/git-proxy-cli/package.json`. You'll have to manually set these according to the appropriate semantic version generated by the release drafter.
76+
77+
As detailed in [`npm.yml`](https://github.com/finos/git-proxy/blob/main/.github/workflows/npm.yml), it:
78+
79+
1. Builds the package
80+
2. Detects whether it's the latest version, according to the current `package.json` (e.g.: if the version you're publishing is `2.3`, and the latest on NPM `2.2`)
81+
82+
- If it's the latest version, it gets tagged as `'latest'` which is the default version that gets installed when calling `npx @finos/git-proxy`
83+
- If it's a maintenance release on an older line, it gets tagged as `release-X.Y` so users can pin it explicitly if needed (either via the tag, or the version itself)
84+
85+
3. Publishes the package to NPM with the tag defined above
86+
87+
### Publishing a Patch Release
88+
89+
For patch releases, the same process applies. The only difference is that first we must perform the cascade-based merge flow from above:
90+
91+
First, we make a PR against the earliest supported version where the bug can be reproduced. Deprecated versions need not inherit the fix. Then, we open a PR against that version's release branch, ex. `release/2.2`. Once the bugfix has been merged, this automatically generates a draft release with a patch bump (ex. `2.2.0` -> `2.2.1`). We **must publish the release** (to prevent the draft from getting overwritten). Finally, we merge (_cascade_) the `release/2.2` branch into the next supported version, ex. `release/3.0`, and repeat the publishing process.
92+
93+
### Cheatsheet and Troubleshooting
94+
95+
The flows are roughly as follows:
96+
97+
#### Releases
98+
99+
1. You merge new PRs to `main`
100+
2. When a milestone is completed, make a PR to bump the GitProxy version on all of the relevant `package.json` files. This is necessary for publishing to NPM.
101+
3. Make a `release/X.Y` branch to freeze feature development. New features and improvements go into `main`, not into the `release/X.Y` branch
102+
4. Upon creating the branch, a draft release is automatically generated.
103+
5. Review the draft release notes, and click Publish if appropriate. This will automatically build and publish to NPM
104+
105+
#### Patches
106+
107+
1. Figure out which is the earliest _supported_ version where the bug can be reproduced. Suppose the latest two major versions are supported (`1.20.x` and `2.2.x`), then we only care about reproducing the bug on `release/1.20` and `release/2.2`.
108+
2. Fix the bug and make a PR against the relevant version
109+
3. In this PR, you **must** also bump the GitProxy version on all relevant `package.json` files for publishing to NPM (ex: `1.20.0` -> `1.20.1`)
110+
4. Once the PR is merged, a draft release will be generated to bump the patch version
111+
5. Review the draft release notes and publish if appropriate. This will automatically **update** the NPM `release-1.20` line with the patched package. **Tip: Don't forget to uncheck the "Set as latest release" default option**
112+
6. Then, make a PR to merge the `release/1.20` branch into `release/2.2`. **Don't forget to bump the GitProxy version for the new line** (ex: `2.2.0` -> `2.2.1`)
113+
7. Repeat steps 4-6 until all the supported versions have been published to both GitHub and NPM
114+
115+
#### Troubleshooting
116+
117+
##### My draft release got overwritten!
118+
119+
This usually happens when forgetting to publish the draft for an older release branch (during cascade merges).
120+
121+
Just re-run the `release-drafter.yml` workflow from the related release branch. Example: If your `1.2.x` draft got overwritten, go to the [Release Drafter action page](https://github.com/finos/git-proxy/actions/workflows/release-drafter.yml), click on the run matching the latest `release/1.2` branch, and then click "Re-run all jobs".
122+
123+
##### I published the draft release and forgot to bump the `package.json`s!
124+
125+
Usually, this will fail to publish to NPM at all. Just delete the bad release from the [GitHub releases page](https://github.com/finos/git-proxy/releases), delete the old related tag, then make a PR to the relevant `release/X.Y` branch bumping the `package.json` versions. When the PR is merged, publish the draft release making sure that a new tag is being created. This should trigger the NPM publish workflow and publish the updated package or override the existing one.
126+
127+
## Questions
128+
129+
If you have any questions or suggestions regarding releases, feel free to [open a discussion](https://github.com/finos/git-proxy/discussions).

0 commit comments

Comments
 (0)