googleapis / googleapis/release-please
Scope Based Versioning
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 588
- Avg merge
- 12h 16m
- Merged PRs (30d)
- 7
Description
## Problem
As far as I understand release-please only considers paths of edited files and commit messages when determining version.
For most projects this is fine, but depending solely on paths start to break down when trying to version more complicated
structures.
Conventional Commit scopes can provide significant context in these situations because they are decided by developers.
Cases such as:
- [**A Multiplayer game**](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/tree/main)
where client and server code lives in the same files.
This example doesn’t do separate versioning for clients and servers, but it is desired when working on multiplayer
games.
With Unity multiplayer frameworks (1st party and 3rd party), shared, client specific and server specific code
are usually in the same files.
Say you fix something you know only effects the server, and clients can still connect to it because of backwards
compatibility.
You create a commit for the server portion of `Grass.cs` with the
message `fix(server): null value in logs when reporting grass count`.
Unfortunately what would have been a simple server side fix rollout is now also a full on client version bump +
release.
- **Mobile Cross-platform frameworks (Flutter, React Native, Xamarin etc.)**
With mobile cross-platform frameworks for iOS and Android there are some cases where you only make changes for one
platform. If you’re actually trying to do SemVer for a cross platform mobile app, you are usually maintaining versions
like `1.0.0-ios.3` and `1.0.0-android.6`, keeping a specific structure
of `major.minor.patch-platform.bump.anythingelse` and parsing that information when uploading to App Store / Play
Store. Whether something is a fix or feat, if it’s scoped to a specific a platform and not about the app in general,
you only bump the platform bump number as to not release an empty change on the not affected platform.
(I'm not sure if release-please supports such a versioning scheme but that should probably be a different feature request if it does not)
## Proposal
Let's add a recursive "scoped-package" field to the spec, with fields inherited from package spec, and two extra fields:
- `scopes: [string]`
- `include-nonscoped: bool`
### "Simple" Manifest Example
```json5
{
"packages": {
// is a path
"src/multiplayer-game": {
"scoped-packages": {
// not a path and not a scope,
// just the package name
"client": {
// anything not explicitly scoped and under this path
// should also bump versions for this component
"include-nonscoped": true,
"scopes": [ "client", "ui" ],
"release-type": "simple"
},
"server": {
"include-nonscoped": true,
"scopes": [ "server" ],
"release-type": "simple"
}
}
},
"separate-pull-requests": true,
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
}
```
Assuming both client and server is at `v1.0.0`, and the game provides backwards compatibility on
major version (as it should):
- `feat(client): improve accessibility`
- blanket client only change, with no server side effect
- bumps client to `v1.1.0`
- server remains at `v1.0.0`
- `feat(ui): add selection for player avatars`
- client also has the "ui" scope, server is headless and ui changes are only possible for clients
- bumps client to `v1.1.0`
- server remains at `v1.0.0`
- `feat(server): add endpoint for manually triggering events`
- server only change, so clients can still connect to this server
- client remains at to `v1.0.0`
- bumps server to `v1.1.0`
- `feat!: client-server udp protocol v2` or
- `feat(client, server)!: client-server udp protocol v2`
- these two commits will have the same effect
- it's a breaking change that affects both clients and servers
- servers will need rollouts, clients will need to update
- bumps client to `v2.0.0`
- bumps server to `v2.0.0`
- `feat(server)!: remove server-side day/night cycle`
- a situation where you must never release with this commit alone
- made a breaking change to server only, now the clients won't be able to connect
- client remains at to `v1.0.0`
- bumps server to `v2.0.0`
### Nested Manifest Example
```json5
{
"packages": {
"src/mobile-multiplayer-game": {
"scoped-packages": {
"server": {
"include-nonscoped": true,
"scopes": [ "server" ],
"release-type": "simple"
},
// example nested components
"client": {
"include-nonscoped": true,
// a commit message with scope client,
// will also effect scopes client/ios and client/android
"scopes": [ "client", "ui" ],
"scoped-packages": {
"ios": {
"include-nonscoped": true,
// nested scope
"scopes": [ "client/ios" ],
"release-type": "simple"
},
"android": {
"include-nonscoped": true,
"scopes": [ "client/android" ],
"release-type": "simple"
}
}
}
}
}
},
"tag-separator": "/",
"separate-pull-requests": true,
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
}
```
Server is the same but now client has "ios" and "android" subscopes.
Note that bumping strategy is just semver, not the one I mentioned in cases.
- `fix(client): ...`
- parent scope, so children are changed
- bumps client-ios to `v1.1.0`
- bumps client-android to `v1.1.0`
- `fix(client/ios): ...`
- bumps client-ios to `v1.1.0`
- client-android remains at `v1.0.0`
- `fix(client/android): ...`
- client-ios remains at `v1.0.0`
- bumps client-android to `v1.1.0`
### Alternatives
I haven’t come across a tool that supports both monorepos and multiple languages as well as release-please.
Contributor guide
Assessment
This issue has not been assessed yet.