Project Best Practices

Introduction

This document provides a high level survey of best practices and suggestions for various aspects of management and maintenance of LF Decentralized Trust (LFDT) projects. In many cases links are provided to other resources at LFDT and beyond for more detailed information.

The best practices generally apply to LFDT Graduated projects. Many of the best practices also apply to Incubation projects, especially Incubation projects that are on a path to become a Graduated project.

The document will first provide a survey of existing guidelines and practices and then dive deeper into areas not covered elsewhere.

Project Incubation Entry Considerations

The Project Incubation Entry Considerations provides baseline suggestions for new Incubations projects. For example:

  • Follow basic open-source practices and licensing
  • DCO sign-offs on commits
  • Diverse set of maintainers and stakeholders

Project Incubation Exit Criteria

The Project Incubation Exit Criteria defines minimum requirements for Graduated projects. These are good suggestions for any project. In a nutshell:

  • Use Apache 2 license
  • Foster an active and diverse contributor community.
  • Provide automated unit and integration test coverage.
  • Provide project documentation.
  • Ensure project infrastructure is in place (Github repository, mailing list, Discord chat, CI).
  • Identify security key contacts and address security vulnerabilities.
    • See Security section for more details.
  • Work towards an OpenSSF Best Practices Badge

Repository structure

Maintainer guidelines

  • Projects should document maintainers along with maintainer roles and responsibilities in a MAINTAINERS.md file.
  • See the maintainers file and sample MAINTAINERS.md for suggested duties of a maintainer and guidance on how to add and remove maintainers.

Inclusive naming

Project governance

  • Use an RFC process (or similar process) to drive consensus and track agreement on project major decisions, features, design, etc.
  • Use Community Specification License v1.0 in RFC repositories - more details TBD
  • Maintainer governance - see Maintainer guidelines above
  • Document project roles and responsibilities (maintainers, release managers, contributors, etc)
  • Document project operational procedures, including how to manage a project roadmap

Fostering a community

  • Foster a welcoming, positive, and public environment where contributions are encouraged. - See Creating an Inclusive Community presentation
  • Decisions should be made in public, or at least socialized in public
  • Engage on Discord Chat - see Suggested Channel Organization and Naming
  • Use Mailing lists for official business - start with a single mailing list, consider multiple if there becomes a need (users list versus contributors/maintainers list)
  • Host public meetings on a regular cadence. Ask community about best meeting time, consider two meetings to cover different regions, or rotating meeting times (shifted 8 hours or 12 hours).

Finding and encouraging new contributors

Project management and issues

  • Maintain a written project roadmap, discuss in project meetings
  • Create, clarify, and label issues in Github for contributors. Use Github default labels, e.g. “good first issue”
    • Consider splitting “good first issue” label into multiple labels, e.g. “good-first-issue-100-introductory” through “good-first-issue-400-expert” (see Cacti project)
  • Review, triage, comment on, and close inbound Github issues

Pull Request management

  • Quick review turnarounds are appreciated and encourage future contributions (and shows up in Insight reports).
  • Equal attention to PRs - review in order of arrival as a general rule of thumb.
  • ‘Over’-communicate in PR comments, especially if review is delayed - contributors don’t know what is in a maintainer’s head
  • Be gentle on new contributors, perhaps relax coding guidelines and fix up later
  • Don’t leave contributors hanging… if the contribution is not a good fit say so
  • Mentor new contributors through the process, in PRs and otherwise

Security

  • Provide three named security contacts per project
  • Define security issue reporting process in SECURITY.md with reference to Security reporting process
  • Review, respond, and act on reported security vulnerabilities
  • Leverage automated scans, tooling depends on language but usually includes some combination of:
    • linters
    • Software Composition Analysis dependency scans, e.g. Dependabot, Govulncheck
    • Static Application Security Testing (SAST) aka static analysis scans, e.g. CodeQL, Snyk
  • Pin dependencies and keep dependencies up to date, e.g. using Dependabot, although be wary of auto-upgrades and lookout for malware.
  • Engage with LFDT staff on possibility of security audits for Graduated project major releases; address audit results and socialize
  • Review OpenSSF secure developer guide and OpenSSF overview presentation to TAC (charts, replay)
  • Review and obtain OpenSSF Best Practices Badge - see criteria
  • Sign release artifacts (TBD) - see proposed Security Artifact Signing task force
  • Also see 2022 security task force

Documentation

  • Documentation should minimally target the following audiences
    • User guide including Getting Started / Tutorial
    • Project developer guide including coding guidelines, design docs, build instructions, test instructions
    • Application developer guide
  • See the documentation template lab for an example of what to include in documentation
  • Documentation task force will address Common styling guide, Recommended common publishing platform, Document best practices for creating documentation, etc.

Releases

  • Follow an established Release taxonomy - either SemVer or CalVer; use consistent pre-release tags (e.g. -preview, -alpha, -beta)
  • Document release strategy and release process including required approvals
  • Document branch strategy, e.g. one branch per major.minor release works well so that it can be maintained in isolation while delivering major.minor.patch releases
  • Document Long-term support (LTS) release strategy - Fabric example
  • Use Github Actions to automate release process, e.g. publish artifacts and release notes upon drafting a GitHub release
  • Use Reproducible builds
  • Sign release commits with GPG (-S or –gpg-sign); sign release artifacts - see Security Artifact Signing task force
  • Release artifacts
    • binaries attached to GitHub release
    • NPM packages - don’t publish on every commit due to NPM limit of 1000 versions

Continuous Integration

  • GitHub Actions is the recommended CI platform, although use efficiently due to limits on number of runners, some ideas to limit runner usage:
    • Use cancel-in-progress to suppress multiple jobs for multiple pushes to the same pull request
    • Uncheck branch protection rule “Require branches to be up to date before merging” to reduce number of runs (potentially add a scheduled run if you are concerned about incompatible PRs getting merged)
    • Use filters to eliminate unnecessary runs, e.g. doc PRs shouldn’t require building and testing code.
    • Consider running some jobs on schedule (nightly) rather than on each pull request (e.g. full matrix of platform tests)
    • Inspect Github Actions run results on your own fork prior to opening Pull Request
    • Contact LFDT staff for the possibility of dedicated paid runners
  • Pull request checks
    • DCO - Developer Certificate of Origin
    • Unit tests
    • Integration tests
    • Scans - see Security section, consider running on schedule (nightly) rather than on each pull request
    • Note - just because a change passes automated checks doesn’t mean it is necessarily good, it still requires judicious maintainer review
  • Test coverage reporting - run on-demand or nightly
  • Keep CI clean and green at all times, address failures and flakes
  • See also proposed Automated Pipelines task force

GitHub configuration

  • Define repository settings in .github/settings.yml so that they can be managed and tracked via pull requests, see Fabric example.
  • Consider using a CODEOWNERS file to specify write permission per directory
    • See Fabric example with additional /docs maintainers.
    • Add a link from CODEOWNERS to MAINTAINERS.md scope field so that users can find domain area contacts
  • Consider using a .github/PULL_REQUEST_TEMPLATE.md and .github/ISSUE_TEMPLATE
  • Define Branch protection rules. Recommended configuration:
    • Check Require a pull request before merging
    • Check Require approvals
    • Check Dismiss stale pull request approvals when new commits are pushed
    • Check Require review from Code Owners to enforce CODEOWNERS file.
    • Check Require status checks to pass before merging
    • Uncheck Require branches to be up to date before merging to limit CI runs
    • Check Restrict who can push to matching branches
    • The remainder can remain unchecked unless there is a specific need
  • Use Reusable github actions to reduce the number of top-level checks

GitHub workflow

  • Although there are often multiple paths to achieve an outcome in git and GitHub, there is value in defining a suggested path for contributors, both for the benefit of new GitHub users, and for the sake of project consistency.
    • See the LFDT GitHub Contribution Guide for detailed guidance on forking, branching, remotes, creating pull requests, updating pull requests, and cherry picking
  • Rebase merging is preferred over Merge commits and Squash merging to keep commit history and PR description clean (assuming contributors squash/amend their own pull requests)
  • Nice to haves (consult the GitHub Best Practices documentation for details)
    • Try to have all the commits signed on your default branch. This is hard to do in practice, but could come in handy later.
    • Try to reduce the load on the CI by preserving the commit hashes post-merge (e.g. the commit hash on the main branch matches the commit hash from the pull request branch)
      • This makes it so that some CI tasks can be skipped on the main branch, thus reducing the load on the CI.