Permalink
Fetching contributors…
Cannot retrieve contributors at this time
260 lines (170 sloc) 15.1 KB

Contributing

When to add a plan to core plans

Habitat Plans are packages in the Habitat Core Origin. They are maintained and built by the core maintainers to provide the fundamental base tier of packages used by the Habitat ecosystem.

Participation in the Habitat community is governed by the code of conduct.

You can browse all available packages that you can leverage and use, including packages built and maintained by community members both inside and outside of this core origin, in Habitat Builder.

Keep in mind that a core plan must by definition be abstracted to serve a wide array of users in service of their applications. If you are building a plan that is tailor made for your own unique application or specific use case, it is better suited to your own origin. Packages can be made public in your own origin too. Community and external project owned origins are an awesome way to make, share, and use functionality that lives outside of and extends core plans.

Requirements to add a plan to core plans

In order for a package to be accepted as a core package, the following requirements must be met:

Package Metadata

Each package plan in this repository must contain a value adhering to the guidelines for each of the following elements:

  • pkg_description
  • pkg_license (in SPDX format)
  • pkg_maintainer in the format of "The Habitat Maintainers humans@habitat.sh"
  • pkg_name see the section of this document on "Package Name Conventions"
  • pkg_origin must be set to core
  • pkg_source
  • pkg_upstream_url
  • pkg_version must be the complete version number of the software

Package Name Conventions

Each package is identified by a unique string containing four sub-strings separated by a forward slash (/) called a PackageIdent.

`origin`/`name`/`version`/`release`

The origin, name, and version values of this identifier are user defined by setting their corresponding variable in your plan.sh file while the value of release is generated at build-time.

The value of name should exactly match the name of the project it represents and the plan.sh file should be located within a directory of the same name in this repository.

Example: The plan for the bison project project contains setting pkg_name=bison and resides in $root/bison/plan.sh.

There is one exception to this rule: Additional plans may be defined for projects for their past major versions by appending the major version number to its name. The plan.sh file for this new package should be located within a directory of the same name.

Example: the bison project maintains the 2.x line along with their current major version (at time of writing: 3.x). A second plan is created as bison2 and placed within a directory of the same name in this repository.

Packages meeting this exception will always have their latest major version found in the package sharing the exact name of their project. A new package will be created for the previous major version following these conventions.

Example: the bison project releases the 4.x line and is continuing to support Bison 3.x. The bison package is copied to bison3 and the bison package is updated to build Bison 4.x.

Adding an older version of a core package

Sometimes you may need a version of software that we are packaging which was released before the project's corresponding Habitat core package was created.

Please do not issue a PR containing a new plan for the specific version of software that you need unless the software project it packages meets the exceptional cases outlined in the above section "Package Name Conventions". Instead create an issue containing the name and version of the software that you want published to Habitat Builder. A maintainer will run a one-off build and publish the generated artifact to the public depot and close your issue once the work is completed.

Issues with an associated gist containing a working fork of our current plan which builds the version of the software will be attended to first.

Dependencies

If your package has dependencies, it must only depend on other packages in the core origin.

Pinned versions are not allowed as they prevent package rebuilds and will cause dependencies conflicts.

Plan syntax

You can review the entire plan syntax guide here.

Please note that the following conditions must be observed for any plan to be merged into core plans (and are important best practices for any plan):

Plan basic settings

You can read more about basic plan settings here. The minimum requirements for a core plan are:

  • pkg_name is set
  • pkg_origin is set
  • pkg_shasum is set
  • pkg_description is set

Callbacks

You can read more about callbacks here. The minimum requirement for a core plan are:

Do's

  • do_prepare() is a good place to set environment variables and set the table to build the software. Think of it as a good place to do patches.

Don't's

  • You should never call exit within a build phase. You should instead return an exit code such as return 1 for failure, and return 0 for success.
  • If you clone a repo from git, you must override do_verify() to return 0.
  • Never use pkg_source unless you are downloading something as a third party.
  • You should never shell out to hab from within a callback. If you think you want to, you should use a utility function instead.
  • You should not call any function or helper that begin with an underscore, for example _dont_call_this_function(). Those are internal only functions that are not supported for external use and will break your plan if you call them.
  • Don't run any code or run anything outside of a build phase or bash function.

Hooks

The supervisor dynamically invokes hooks at run-time, triggered by an application lifecycle event. You can read more about hooks here.

  • You cannot block the thread in a hook unless it is in the run hook. Never call hab or sleep in a hook that is not the run hook.
  • You should never shell out to hab from within a hook. If you think you want to, you should use a runtime configuration setting instead. If none of those will solve your problem, open an issue and tell the core team why.
  • Run hooks should:
    • Redirect stderr to stdout (e.g. with exec 2>&1 at the start of the hook)
    • Call the command to execute with exec <command> <options> rather than running the command directly. This ensures the command is executed in the same process and that the service will restart correctly on configuration changes.
    • If you are running something with a pipe exec won't work.
    • Always assume a minimal BusyBox sh implementation, never GNU Bash unless core/bash is an explicit run dependency and the hook's shebang line calls this Bash interpreter directly.
  • Attempting to execute commands as a root user or trying to do sudo hab install are not good practice.
  • Don't edit any of the Supervisor rendered templates.
    • You can only write to: /var/, /static/, /data/ directories. You should only access these with your runtime configuration setting variable.
    • No one should ever edit anything in /hab/ directly.
    • No one should write to anything in /hab/ directly.

New Plans

Adding a new plan to core-plans requires updating .bldr.toml with your new package plan. This is so that Builder can map all of the plans to their respective directories.

README

Check out the core plans README template for a quick start!

All plans should have a README. In core plans, it is a hard requirement. Your README at a bare minimum should include:

  • Your name as maintainer and supporter of this plan.
  • Absolutely required:
    • What habitat topology it uses (and the plan should have the correct topology for the technology).
    • Clear, step by step instructions as to how to use the package successfully.
    • What is the best update strategy for different deployments?
    • What are some configuration updates a user can make, or do they always need to do a full rebuild?
  • Strongly recommended:
    • Documentation on how to scale the service.
    • Instructions on how to monitor the health of the service at the application layer.
    • Can a user simply call the package as a dependency of their application?
    • How does the package integrate into their developer workflow?

Linting Your Plans

It is good it use a tool to lint your plans to ensure you are not making any easy-to-catch mistakes in your scripting. We recommend running ShellCheck against your plans.

Some default checks of ShellCheck can be turned off, since they aren't necessarily applicable in plans. The following options work well:

shellcheck --shell=bash --exclude=SC1090,SC1091,SC2034,SC2039,SC2148,SC2153,SC2154,SC2140

If ShellCheck is installed, you can run this (and other checks) locally with:

git add <your changes> && pre-commit run

See below for more about the pre-commit hooks.

Pre-commit hooks

Install pre-commit to run prior to your commits. This will perform some initial checks against your changes and recommend any fixes before you commit.

Signing Your Commits

This project utilizes a Developer Certificate of Origin (DCO) to ensure that each commit was written by the author or that the author has the appropriate rights necessary to contribute the change. The project utilizes Developer Certificate of Origin, Version 1.1

Developer Certificate of Origin
Version 1.1

Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.


Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.

Each commit must include a DCO which looks like this

Signed-off-by: Joe Smith <joe.smith@email.com>

The project requires that the name used is your real name. Neither anonymous contributors nor those utilizing pseudonyms will be accepted.

Git makes it easy to add this line to your commit messages.

  1. Make sure the user.name and user.email are set in your git configs.
  2. Use -s or --signoff to add the Signed-off-by line to the end of the commit message.

Separate Changes, Separate Pull Requests

Each package being changed should be separated into its own pull request. E.g. If you are making a change to core/openssl and your change requires another change in core/curl to be merged, each of these changes should be submitted as two different PRs with a note about the order in which each thing should be submitted.

Each of these change PRs submitted should include a bracketed packagename as the prefix to the change information. For example in the previously defined situation the PR titles above might titled like so:

  • [curl] Making a change here
  • [openssl] Also making a change here

If you have opened a single PR that changes multiple plans, it is assumed you are making a substantial change to core plans. Substantial change PRs submitted without an RFC will be closed and you will be directed to open an RFC. If this was not your intention please open separate PRs per package change. RFCs live in their own repository. To open one, write one up according to the template, and open a pull request.

Pull Request Review and Merge Automation

Habitat uses a bot to automate merging of pull requests. Messages to and from the bots are brokered via the account @thesentinels which can process incoming commands from reviewers to approve PRs. These commands are routed to a sentinel bot that will automatically merge a PR when sufficient reviewers have provided a +1 (or @thesentinels approve in sentinels terminology).

We use GitHub's integrated CODEOWNERS to determine a appropriate reviewer(s). You must receive an approval from at least one CODEOWNER if there is one present for the plan you are modifying.

Add yourself as a CODEOWNER

You may optionally add yourself as a CODEOWNER of a plan. Adding yourself as an owner means you have a vested interest in the software packaged by the plan and you, or another owner of the plan, will be required to review suggested changes. At least one CODEOWNER's approval is always required for a change to be accepted even if the change has been reviewed by a core plans maintainer.

Add yourself to core plans maintainers

You can add yourself to core plans maintainers to take a greater role and responsibility in the care, feeding, and maintenance of all core plans.