diff options
author | Didier Wenzek <didier.wenzek@free.fr> | 2022-08-30 16:08:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-30 16:08:46 +0200 |
commit | be4cd2ec061938b8777529ae6c7a915f73f3544a (patch) | |
tree | 8f689ccff7072318fdf14a2f3d00e540b3021cc8 | |
parent | fe3645a3fa0f30c459e7b2feea35eda89dfc8006 (diff) | |
parent | cf039bbbc40d71d9b5938e84af3bdb5cf648d747 (diff) |
Merge pull request #1203 from didier-wenzek/rfc/governance
Agreement on a governance model for thin-edge
Signed-off-by: Didier Wenzek didier.wenzek@free.fr
Signed-off-by: Marcel Müller m.mueller@ifm.com
Signed-off-by: Matthias Beyer <matthias.beyer@ifm.com>
Signed-off-by: Rina Fujino <18257209+rina23q@users.noreply.github.com>
Reviewed-by: Andrej Schreiner
Reviewed-by: Matthias Betz
-rw-r--r-- | GOVERNANCE.md | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 00000000..647ff610 --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,459 @@ +# Governance thin-edge.io + +This documents serves as a guiding document to ease technical decision-making in the project as a whole. + +Some of its goals are: + +- Making sure that the different stakeholders are represented with their requirements +- Making sure that contributors know how decisions are made and who they can address concerns/questions to +- Making sure that team members know what is required of them for the project + + +## The project vision + +In the [vision.md](./vision.md) the goal of the project is encoded. +It specifies the different functional requirements and non-functional requirements of the project as a whole. +All the stakeholders must agree on the vision upon joining. + +- The current stakeholders are: Software AG, and IFM + +Changes to the vision need to be done in a plenum of stakeholders, this makes sure that everyone is aware and agrees to the evolution of the project. + + + +## Team Structure + +* Teams are either single contributors or a group of them +* They are responsible for a specific part of project, and as such are the maintainers of those parts + * This includes: Reviewing pull requests, triaging issues in their assigned area, and general maintenance +* Each team is assigned a single or multiple subtrees of the project, as defined by the project structure +* The teams follow the project hierarchy for decisions, i.e. higher decisions take precedence + +The important bits: + +At the 'top' are the maintainers, whose job is to define and realize the project vision of thin-edge.io. +Maintainers should strive for agreement based on the following factors: + +- The vision of the whole project +- Feasibility, accounting for future technical and cultural shifts +- The health of the project going forward + +The maintainers ensure that all changes in the project align with the agreed vision +and support the health of the project and its community without being unduly influenced from their employers. + +Underneath the maintainers are the teams or individuals, that each are allowed to make similar decisions about the project *in the area they have been delegated*. + + +- Some decisions are global in the project, like the core/API + - Team members should try to make sure to explore possible options together before calling for time-consuming solutions like a vote. This mostly includes uncontroversial changes that are low impact or have already been agreed upon + - If an exclusive choice has to be made (where it is not possible to entertain two conflicting approaches), and no clear side is more advantageous to pick, a vote should be held with the majority opinion being the final decision. + +- Some decisions are local, e.g. a plugin does not impact others with its behaviour, however it still needs to be a 'good citizen' in the project (CI, format, etc..) + - These should be clearly scoped in their respective project part + - However, if needed a 'higher up' decision can be requested if no consensus is achieved + + + +## Project Structure + +The project has a hierarchy to solve these two problems: + +1. How can users make sure that their voice and interests are represented in the project? + - Each member party appoints one core team member + - They form the group of people that have to, and are responsible for, signing off on the technical implementation of the project +2. How to make the lives of these team members easier? + + +----- + +* Thin-edge is organized around sub-projects - to ease decision taking. + * The sub-projects are organized in a hierarchy + * This makes it easier to decouple different parts of the project + * This makes it easier to decide on technical questions + * Everyone has to agree on the core project as it is the foundations to all others. + * At the periphery, sub-projects might be related to specific eco-systems (e.g. Cumulocity or Moneo) and therefore have independent decision processes. + * At an intermediate level, one might have sub-projects related to specific use-cases like “JSON over MQTT”. +* All the sub-projects share a common repository - to ease consistency across projects and over time. + * Labels are used to organize issues/PRs/discussions along sub-projects. + * Code ownership is used to enforce cooperation around key components, but the default is to let things open and to trust each other, using version control as a safety net. + + + + + + +``` +core contributors = [SAG, IFM] + +-> Project leads, one each from [core contributors] +| + \- Responsible for `/*`, aka everything in the repository + | + | + \ + \-> Delegated project Teams, any combination of [teams, individual contributors] + | + |\- Responsible for `/plugins/plugin_{foo,bar}` + ||- Are trusted by the project leads (who would have to stand-in for the trusted members) + | + |-> Can be needed to nest further if the project grows bigger +``` + +## Repository maintenance + +To assure a consistent level of quality and appearance, the project has some rules for contributors to follow: + +- **Clear commits** + Having clear, concise and well-written commit messages for all changes is not + only a indicator for the seriousness of the project, but also a way to ensure + sustainable development via replicability of the sources of the project. + + Because of this, we try to ensure the highest possible quality for each + individual commit message. + + Because such a thing cannot necessarily or in full be enforced via tooling, it + remains mainly the obligation of a reviewer of a change-set to ensure + + * Atomicity of the individual commits + * that one commit is one atomic change, and not an accumulation of several + individual and separate changes + * that the commit message of the change expresses why the change was made + + Every reviewer of a pull request is asked to review not only the changes, but + also the commit messages. + Reviewers are explicitly empowered and actually encouraged to block pull + requests that contain commit messages that do not meet a certain standard + even and especially also if the proposed changes are acknowledged. + + The contributor should document why they implemented a change properly. A good + rule of thumb is that if a change is larger than 60 lines, a commit message + without a body won't suffice anymore. + The more lines are touched by an individual commit, the more lines should be + used to explain the change. + + The project implements lints using github actions to meet such criteria. + + Also, some hard criteria is checked via github action lints: + + * The `Signed-off-by` trailer lint must be present in all commits (also see + section "Ensuring the Signed-off-by-trailer") + * The commit body must meet the default formatting of a commit message, that + is + * Subject line not longer than 50 characters + * Subject capitalized + * No period at the end of the subject + * Imperative mood in the subject + * Second line empty + * Body lines not longer than 72 characters + + Commits using the `--fixup` or `--squash` feature of `git-commit` are allowed, + but won't be merged (read more about this in the "merge strategies" section). + +- **Ensuring the Signed-off-by-trailer** + Contributors need to sign the "Contributor License Agreement". They do so by + signing off each individual commit with a so-called "Signed-off-by Trailer". + Git offers the `--signoff`/`-s` flags when using `git-commit` to commit + changes. + + To ensure that all commits have the trailer present in the commit message, a + CI lint is installed in the github actions workflows of the project. This lint + blocks pull requests to be merged if one or more of the commits of the pull + request misses the `Signed-off-by` trailer. + + As a result, it is not possible to merge pull requests that miss the trailer. +- **Coding styleguide** + Coding style is enforced via `rustfmt` in its default configuration. + Compliance with the coding style is enforced via CI. +- **Testing** + Testing is done via workflows in github actions using `cargo test --all-features` for all + crates. + The main objective with this is that a developer should be able to simply run + `cargo test` on their local machine to be able to see whether CI would succeed + for changes they submit in a pull request. + Thus, all CI tests (unit tests, but also integration tests) are implemented in + Rust and do not rely on external services. + End-to-end system tests - that depend on external services - are run outside the CI pipeline, + to avoid inconsistent test outcomes because of external issues. +- **Benchmarks** +- **Documentation builds** + Source code documentation as well as other documentation is tested via github + actions workflows as well, to ensure that a developer is able to build all + relevant documentation on their local machine. +- **Keeping spec up to date** +- **Evergreen master** + The project pursues the "evergreen master" strategy. That means that at every + point in time, the commit that `master`/`main` points to must successfully + build and pass all tests. + + Reaching that goal is possible because of the employed merge strategies (read + below). +- **Merge strategies** + Merging is the way how the project accepts and implements changes. + + Because of the pursued "everygreen master", merging is implemented in a + certain way that forbids several bad practices which could lead to a breaking + build on the `master`/`main` branch, and a special workflow is implemented to + ensure not only the "evergreen master" but also to streamline the workflow for + integrating pull requests. + + The following actions are **not** allowed: + + * Committing to `master`/`main` directly. + The GitHub repository is configured to block pushing to `master`/`main`. + * Squash-Merging of pull requests (which is equivalent to committing to + `master`/`main` directly). + The github repository is configured to not allow squash merges. + * Merging of "fixup!" or "squash!" commits. A github actions + job is employed to block pull requests from being merged if such commits are + in the branch of the pull request. Rebase should be used to clean those up. + + It is explicitly _not_ forbidden to have merge-commits in a pull request. + Long-running pull requests that contain a large number of changes and are + developed over a long period might contain merges. They might even merge + `master`/`main` to get up-to-date with the latest developments. Though it is + not encouraged to have such long-running pull requests and discouraged to + merge `master`/`main` into a PR branch, the project acknowledges that + sometimes it is not avoidable. + + To summarize, the following requirements have to be met before a pull request + can be merged: + + * Reviews of the relevant persons (ensured via github setting) + * Status checks (CI, lints, etc) (ensured via github setting) + * builds, tests, lints are green (ensured via github action) + * Commit linting (ensured via github action) + * No missing `Signed-off-by` lines (ensured via github action) + * No "fixup!"/"squash!" commits in the pull request (ensured via github + action) + + Merging itself is implemented via a "merge bot": [bors-ng](https://bors.tech). + bors-ng is used to prevent "merge skew" or "semantic merge conflicts" + (read more [here](https://bors.tech/essay/2017/02/02/pitch/)). +- **Dependency updates** + Dependencies should be kept in sync over all crates in the project. That means + that different crates of the project should try to use dependencies in the + same versions, but also that dependencies should be harmonized in a way that a + specific problem should not be solved with more than one external library at a + time. + Updates of dependencies is automated via a github bot + ([dependabot](https://github.com/dependabot)). + To ensure harmonization of dependencies, a dedicated team (see "Team + Structure") is responsible for keeping an eye on the list of dependencies. +- **License linting** + License linting describes the act of checking the licenses of dependencies and + whether they meet a certain criteria. + For example, it is not feasible to import an external library that is licensed + as GPL-3.0 in an Apache-2.0 licensed codebase. + Because of this, a github action is installed to lint the licenses of + dependencies. This action runs as a normal lint (see "evergreen master") and + blocks pull requests if dependencies get imported that do not meet a set of + rules agreed upon by the project maintainers. + +## Release workflow + +The following describes how thin-edge.io is released. + +The following chapters do not talk about major releases (increasing "x" in a +"x.y.z" version number) as there is no workflow for these implemented yet. + + +### Preface + +The following chapter describes the release process of the thin-edge.io project +and the corrosponding crates. + +The goal of the workflow described in this chapter is to have _as little impact +as possible_ on the general development of the project. +Releases should _never_ stop, prevent or even just slow down the normal +development of the project. +For example, halting development on the `main` branch and forbidding +contributors and maintainers to merge changes to it even for as little as one +hour just so that a new release can be published is not acceptable. +Also should "patch" releases (sometimes called "bugfix releases") have no impact +on the project pace or even concern developers - they should just happen in +parallel without any influence on the normal development activities. + +With these requirements, we implement the following workflow. + +### Semver conformity and API coverage + +We adhere to [semver](https://semver.org), +with the [exceptions implied by the cargo implementation of the standard](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-cratesio). + +Parts of the API that are covered by semver are explicitly marked. Our public +API is extensively tested in integration tests. If changes to the public API of +thin-egde.io are necessary, these changes are documented in the `CHANGELOG.md` +file of the project, with reasoning why the change was necessary and how users +can upgrade to the new interface(s). + +<!-- TODO: Expand on how exactly these changes are documented? --> + +We also define the following rules for our release process: + +* We release new features by increasing the "minor" version +* When we release new patch releases, these releases never contain new features, + but only fixes to bugs. + +### Release cycle + +Minor releases are published roughly every TBD months. + +Until a minor release is published, the previous minor release _can_ receive +patch releases (accordingly to [semver](https://semver.org/)). + +### Strategy + +We use the release-branch strategy, where development happens on the `main` +branch and releases are done on dedicated `release-X.Y.Z` branches. + +Because we employ the "evergreen main branch" strategy and all of our merge +commits on the `main` branch are guaranteed to successfully build and pass CI, a +release can potentially be made starting from every commit on the `main` branch. + +For a description of the release workflow, read below. + +### Release maintainer + +For every release, one or more "release maintainers" are appointed by the core team. + +The responsibilities of the release maintainers are: + +* Creation and maintenance of the `release-x.y.z` branches +* Cherry-picking bugfix patches from the `main` branch and applying them to the + relevant `release-x.y.z` branch (via pull request to that branch) + * If a patch does not apply cleanly, it is _not_ the responsibility of the + release maintainer to make the patch apply. It is responsibility of the + release maintainer, though, to talk to the developer of the patch and work + with them to port the fix back to the release +* Create git-tags for the release(s) as appropriate +* Create github artifacts (or take care of a github-action pipeline that does) + for releases +* Port the changes to the `CHANGELOG.md` file back to `main` (via pull request) +* Submit pull requests to the `main` branch to update all version numbers for + the next release cycle + +It is explicitely allowed for everyone to open bugfix-backport pull requests to +a release branch, but the release maintainer(s) decide when and how to apply +them to the release branch. + +### Release branches + +Release branches MUST be named with a pattern. This pattern is + +``` +"release" dash <major version number> dot <minor version number> dot "x" +``` + +The `"x"` is used instead of the "patch version number", because patch releases +are published from the release branches (read below). + +A release branch gets the following rules enforced via GitHub: + +* Only the "release-maintainers" team can create branches named `"release-*"` +* Pull requests are required on these branches +* Status checks are required to succeed on these branches +* "CODEOWNERS" is **not** enforced on these branches +* These rules are also enforced for administrators + +### Workflow for minor releases + +The following steps happen when a minor release is made: + +1. One release maintainer creates a branch, starting from a recent commit on + `main`, named after the aforementioned naming rule. +2. It is ensured that this branch cannot be pushed to by anyone except the + [bors merge bot](https://bors.tech) + (Refer to the "Merge strategies" point in the "Repository maintenance" + chapter for more information) +3. The release maintainer crafts the `CHANGELOG.md` entries for this release and + opens a pull request for it, targeting the aforementioned release branch. +4. Once agreed upon with everyone involved, they merge the PR for the + `CHANGELOG.md` to the release branch +5. The release maintainer publishes the release on crates.io and creates a new + tag for the release. + They might add a tag message as they seem appropriate. + They then push the tag to the GitHub repository of the project. + They also make sure that release artifacts are published on GitHub for the + new release (or make sure that a github-actions pipeline does this) +6. After the release is done, the `CHANGELOG.md` changes are cherry-picked to a + pull request to the `main` branch by the release maintainer +7. After the release is done, the release maintainer opens a pull request to the + `main` branch to update all version numbers of all crates to the next minor + version + +### Workflow for patch releases + +Patch releases are published when appropriate, there is no fixed release cycle. +It might be a good rule-of-thumb to not release more than one patch release per +week. + +#### Backporting + +Bugfixes that are added to a patch release _must_ have been applied to the +`main` branch, before they are backported to the appropriate `release-x.y.z` +branch. +If a bugfix that is applied to `main` cannot be backported, due to either +conflicts or because the feature that is about to be fixed does not exist in the +`release-x.y.z` branch anymore, the patch may be adapted to apply cleanly or a +special patch may be crafted. +The release maintainer is encouraged to reach out to the developer of the patch, +as it is _not_ the responsibility of the release maintainer to adapt patches. + +In any case, fixes that are backported to a `release-x.y.z` branch, MUST pass +CI and thus MUST be submitted to the release branch via a pull request. + +#### Publishing of patch releases + +A patch release is published as soon as the release maintainer thinks it is +appropriate. + +The steps the release maintainer follows are almost the same as the steps of the +minor release workflow: + +* The release maintainer submits a pull request to the release branch with the + following changes: + * `CHANEGLOG.md` entries for the patch level release + * Updates of the version numbers for all crates in the "patch"-level position, + e.g. "0.42.0" becomes "0.42.1", +* Once the aforementioned pull request is merged, the release maintainer + publishes the release on crates.io, tags (`git tag -a vMAJOR.MINOR.PATCH`) + the release and pushes the tag to the GitHub repository of the project +* Once the release is published, the release maintainer opens a pull request to + the `main` branch of the project, porting the changes that were made to the + `CHANGELOG.md` file to this branch + +### More + +The `CHANGELOG.md` is added on the release branch rather than on the `main` +branch. The reason for this is the workflow: If the changelog is adapted on +`main`, the branchoff for the release branch can _only_ happen directly after +the changelog was merged, because other merges may introduce new changes that +need to be in the changelog. Also, the changelog-adding pull request must be up +to date all the time, if patches get merged to `main` _while_ the changelog is +written, the changelog would need further fixes. +If the changelog is added on the release branch, no synchronization is +necessary, as the branchoff for the release already happened. +Instead, the changelog entries can be "backported" to `main`, which is trivial. + +In a similar fashion are patch-level `CHANGELOG.md` entries ported to the `main` +branch. + +Version number bumps happen right _after_ branchoff for a release. Doing the +version number bump before the release would mean that the release maintainers +would have to wait for the version-bump-pull-request, which is not acceptable +under the preassumption that every commit from `main` can potentially be +released. +By bumping the numbers right _after_ the release, but for the next release, we +automatically get a peace-of-mind state for that next release, where the release +maintainers can again just take any commit on `main` and start their release +process. + +The implication of the patch-level release workflow is that the `main` branch +does never see changes to the version strings of the crates in the "patch" level +position. This is intentional, as there is no need for that. + + +## Related + +* [Understanding open source governance models](https://www.redhat.com/en/blog/understanding-open-source-governance-models) +* [Producing Open Source Software](https://producingoss.com/en/producingoss.html) |