Skip to content

Latest commit

 

History

History
627 lines (509 loc) · 25.4 KB

CONTRIBUTING.md

File metadata and controls

627 lines (509 loc) · 25.4 KB

Contributing to staged-script

Thanks so much for your willingness to help out with staged-script's development 😀 Here's everything you need to know.

Contributor License Agreement

By contributing to this software project, you are agreeing to the following terms and conditions for your contributions:

  • You agree your contributions are submitted under the license used by this project.
  • You represent you are authorized to make the contributions and grant the license. If your employer has rights to intellectual property that includes your contributions, you represent that you have received permission to make contributions and grant the required license on behalf of that employer.

Setting Up Your Environment

Before you begin hacking on staged-script, you'll need to do a few things:

  1. Fork the Repository: On staged-script's main page, in the top-right corner, you'll see a button to fork the repository. Do so, and then clone your fork and set it up with
    git clone [email protected]:${USER}/staged-script
    cd staged-script
    git remote add upstream [email protected]:sandialabs/staged-script
    git fetch upstream
  2. Set Up your Environment: Install the requirements with
    cd /path/to/staged-script
    python3 -m pip install \
      -r requirements.txt \
      -r doc/requirements.txt \
      -r example/requirements.txt \
      -r test/requirements.txt
  3. Run the Examples: Ensure you can run all the examples with
    cd /path/to/staged-script/example
    ./run-all.bash
  4. Build the Documentation: Ensure you can build the documentation with
    cd /path/to/staged-script/doc
    ./make-html.bash

Pre-Commit

We use pre-commit to ensure adherence to good software development practices, enforce our style guide, etc. To set yourself up with it, ensure you have your development environment activated, and then run

cd /path/to/staged-script
pre-commit install
pre-commit install --hook-type commit-msg --hook-type pre-push

The checks we perform are the following:

  • Use ruff to lint and format the code and docstrings.
  • Use mypy to run static type checking on our type-hinted code.
  • Ensure no large files are added to the repository.
  • Ensure files parse as valid Python.
  • Check for files that would conflict in case-sensitive filesystems.
  • Ensure files don't contain merge conflict strings.
  • Ensure files end with a single blank line.
  • Ensure we only use Unix line endings.
  • Trim trailing whitespace.
  • Ensure we use type-hinting.
  • Check for common mistakes in reStructuredText in our documentation.
  • Use doc8 to enforce our style for our documentation.
  • Use pyroma to ensure our package complies with the best practices of the Python packaging ecosystem.

VS Code

Our IDE of choice is VS Code. Download and install it, and then follow the instructions below to get it set up.

Getting Started

For getting up and running with VS Code, check out the following resources:

Extensions

VS Code is highly customizable through the use of extensions. Click on the building blocks icon on the left-hand side to open the EXTENSIONS panel to search for and install them. These are the ones we recommend:

General

  • Better Comments: Style comments in a more human-friendly manner.
  • Code Spell Checker: Catch spelling mistakes in code and comments.
  • Conventional Commits: Adhere to the Conventional Commits specification for commit messages.
  • Coverage Gutters: Display test coverage in the editor.
  • GitLens — Git supercharged: Integrate some of the powerful features of GitKraken into VS Code.
  • IntelliCode: AI-assisted development features.
  • Pre-Commit: Commands and helpers for executing pre-commit hooks.
  • Test Adapter Converter: Converts from the Test Explorer UI (below) API to native VS Code testing.
  • Test Explorer UI: Extensible user interface for running your tests in VS Code.
  • Vim: For when you can't truly leave vi behind (and who would want to?).
  • vscode-icons: Icons for the file explorer.

Python-Specific

  • AREPL for python: Automatically evaluate Python code as you type in the editor.
  • autoDocstring - Python Docstring Generator: Quickly generate docstrings for Python functions.
  • Mpy Type Checker: Type checking support for Python.
  • Pylance: Fast, feature-rich language support for Python.
  • Pytest IntelliSense: Adds IntelliSense support for pytest fixtures.
  • Python: Rich support for the Python language.
  • Python Indent: Correct Python indentation.
  • Python Test Explorer: Run your unittest, pytest, or testplan tests with the Test Explorer UI (see General above).
  • Python Type Hint: Type hint autocompletion.
  • Ruff: Automatic linting and formatting.
  • Sourcery: Automatic code review and refactoring.

Settings

After installing the various extensions, you'll also want to customize your Settings. Some things can be set in the Settings editor:

  • Text Editor
    • Font
      • Font Family: Add "'Hack FC Ligatured', " to the beginning of the list. You'll also want to install the Ligatured Hack fonts on your system.
    • Files
      • Auto Save: Set to "onFocusChange".
      • Trim Trailing Whitespace: Check.
  • Extensions
    • Conventional Commits
      • Show Editor: Check.
      • Silent Auto Commit: Check.
    • coverage-gutters
      • Coverage-gutters: Show Line Coverage: Check.
      • Coverage-gutters: Show Ruler Coverage: Check.
    • Git
      • Allow Force Push: Check.
      • Autofetch: Set to "true".
      • Enable Smart Commit: Check.
      • Fetch On Pull: Check.
      • Prune On Fetch: Check.
      • Rebase When Sync: Check. This makes it such that you use git pull --rebase when pulling.
      • Show Push Success Notification: Check.
      • Terminal Git Editor: Check.
    • pre-commit-helper
      • Run On Save: Select "all hooks".
    • Python Docstring Generator configuration
      • Docstring Format: Select "google-notypes".
      • Start On New Line: Check.
    • Sourcery Configuration:
      • Token: [Create a free Sourcery account][sourcery], generate a token, and paste it here.
    • Vim
      • Vimrc: Enable: Check.

Other items can be customized in the settings.json file. Consider adding the following snippets:

  • To use ligatures to make multi-character symbols in code more readable, add
    "editor.fontLigatures": true
  • To add vertical rulers to the editor window, add
    "editor.rulers": [
        72,
        79
    ]
    The line at 79 characters is to remind you of the maximum line length, and the one at 72 characters is to remind you of the maximum line length for comments and docstrings (see PEP8).
  • If you'd like the UI to preserve the scope that you're currently editing at the top of the file as you scroll through it, you can add
    "editor.experimental.stickyScroll.enabled": true
  • To turn on search highlighting when using the Vim extension, add
    "vim.hlsearch": true
  • To set up pytest, such that it produces coverage information, add
    "python.testing.unittestEnabled": false,
    "python.testing.pytestEnabled": true,
    "python.testing.pytestArgs": [
        "-v",
        "--cov",
        "--cov-report=html",
        "--cov-report=json",
        "--cov-report=xml",
        "."
    ],

A final setting needs to be configured in the launch.json file. You'll need to add the following to the list of configurations:

"configurations": [
    {
        ... # Existing configuration.
    },
    {
        "name": "Python: Debug Tests",
        "type": "python",
        "request": "launch",
        "program": "${file}",
        "purpose": ["debug-test"],
        "console": "integratedTerminal",
        "env": {
            "PYTEST_ADDOPTS": "--no-cov"
        },
        "justMyCode": false
    }
]

This will make it such that when debugging unit testing, the debugger doesn't restrict itself to only your code.

Choosing a Python Interpreter

Once you've taken care of all the settings above, you're almost ready to start Python development with VS Code. Before you do, though, you'll need to select your Python interpreter. Open the command palette, start typing "python interpreter," and select Python: Select Interpreter. It will pop up a list of Python installations it could find on your system. Pick the one that corresponds to your development environment (see above).

Setting Up PyTest

The last step in setting up VS Code for Python development is to ensure pytest is working. Click on the flask icon on the left-hand side to open the TESTING panel on the left. There will be two collapsible sections labeled TEST EXPLORER. Collapse the top one (it comes from an extension that doesn't quite work for Python testing), and expand the bottom one. You should be able to hover over a test file, click the play button, and see the tests pass. If so, go ahead and click the three dots at the top-right of the TESTING panel and deselect the top Test Explorer.

Running your test suite will generate code coverage information, which you can then view in the editor. After you've run your tests, open up one of your code files, open the command palette, type "coverage," and select Coverage-Gutters: Toggle Coverage. This will highlight covered and uncovered lines in green and red, respectively. You can also view the full coverage report by opening test/htmlcov/index.html.

Coding Standards

Many of our coding standards are applied and enforced using pre-commit (see above). In addition to what's handled automatically, we have the following.

Documentation

Classes and functions should be documented with docstrings using the Google-style format. The contents of docstrings should use reStructuredText formatting. This is so we can use Sphinx to generate our documentation. Additionally, function definitions should utilize type-hinting wherever possible for clarity's sake.

Testing

We use pytest for our unit test suite. To get up-to-speed with what it does and how it works, check out this RealPython tutorial. Also highly recommended is Python Testing with pytest, by Brian Okken.

Please add tests to cover any new functions you create, and adhere to the following guidelines:

  • Each module (module_name.py) should have a corresponding test file (test_module_name.py).
  • Each function/method in a module should have at least one corresponding test.
  • The test order should match the ordering of the functions/methods being tested in the module, such that users can easily scroll through the two files side-by-side.
  • Prefer parametrizing a test function over creating a separate test function.
  • But don't go too crazy with that—use your judgment.
  • Place any fixture definitions at the top of the test file.

Best Practices

  • Docstrings and comments should be grammatically correct English (capitalization, punctuation, full sentences, etc.).
  • Prefer double quotes over single quotes.
  • Use pathlib.Path and associated methods to represent all path-like objects.
  • Use f-strings for formatting strings.
  • Alphabetize class attributes in the docstring and __init__() to ease readability/maintainability/extensibility.
  • Prefer alphabetizing keyword arguments to functions, unless a different ordering would be more logical in a specific situation.
  • Blank lines in functions should be avoided unless preceding a comment indicating a section of code. However, if your function is broken up into sections via comments, consider subdividing it into smaller functions.
  • Prefer imports of the form
    from package import Class
    as opposed to
    import package
    if only using a small handful of things from the package.

Creating Issues

Create issues in GitHub for any work that needs to be done.

Markdown

Markdown is a lightweight markup language with plain text formatting syntax. GitHub uses a form of it for rendering issue and pull request descriptions and comments, wiki pages, and any files in your repositories with a .md extension (such as this one). For more details on what's possible with GitHub-flavored Markdown, see the documentation.

Issue Templates

When creating an issue, select one of the available issue templates, and then follow the instructions that appear in the template.

Labels

The staged-script > Labels page shows you all the labels we use, along with their descriptions. "Type" labels will be applied automatically when an issue is created via the issue template. "Stage" labels are used to keep track of what work is being done at any given time. Other labels can be added as appropriate.

Working Issues

Planning Work

Depending on the needs of the staged-script user base, a project maintainer will schedule issues to be tackled in the near future by applying the "Stage: Soon" label. An issue can then be grabbed by a member of the development team when they have some time available to work on it.

Note: If you're working on something that hasn't been scheduled—e.g., you're tackling a quick bug fix, or are tinkering with a feature you'd like to see added—don't worry about the "Stage: Soon" label; just work on it as per the rest of the guidelines below.

When Work Begins

First switch the label from "Stage: Soon" to "Stage: Development". Next make sure your local master branch is up-to-date with

git checkout master
git pull --ff-only upstream master

Note: You should never be making commits on your master branch. The --ff-only ensures you only update your local master branch if it can be fast-forwarded.

Once master is updated, you then create a feature branch off of it with

git checkout -b <branch-name>

The recommended branch naming convention is to use the issue number, followed by a hyphen, followed by the issue title, all lowercase, omitting special characters, and replacing spaces with hyphens. For instance, if issue number 123 has "Implement Awesome New Feature" as the title, the corresponding branch name would be 123-implement-awesome-new-feature.

As Work Continues

Do whatever work is necessary to address the issue you're tackling. Break your work into logical, working commits. Use the Conventional Commits extension for VS Code (or something similar) to ensure your commit messages adhere to the Conventional Commits specification.

Feel free to commit and push small chunks early and often and then use interactive rebase to reorganize your commits before sharing.

Note: If you rebase a branch that's already been pushed to a remote, you'll wind up changing the history, which will require a force push. That is permissible (even encouraged), but if you've had one or more reviewers or collaborators working with you on the branch, get their buy-in first before doing a force push.

When Work is Complete

While working on your feature in your local <branch-name> branch, other commits will likely make it into the upstream master branch. There are a variety of ways to merge these changes into your local feature branch. One possibility is

git checkout master
git pull --ff-only upstream master
git checkout <branch-name>
git rebase master

though there are others that are equally valid. Once all is well, create a pull request (see below).

Closing Old Issues

If at any point you encounter an issue that will not be worked in the foreseeable future, it is worthwhile to close the issue such that we can maintain a reasonable backlog of upcoming work. Do be sure to include in the comments some explanation as to why the issue won't be addressed.

Pull Requests

The only way changes get into master is through pull requests. When you've completed work on an issue, push your branch to your fork with git push -u origin <branch-name>, and then create a pull request. Apply the same "Type" label as the issue, and then return to the issue and swap "Stage: Development" for "Stage: Review".

Reviews

A project maintainer will review your pull request. Work with them to get your changes into an acceptable state.

Drafts

You may wish to have your changes reviewed by colleagues before they are ready to be merged into master. To do so, create a draft pull request. GitHub will not allow you to merge a draft request. When it's ready for review, you can mark it as ready.

Continuous Integration

GitHub Actions is GitHub's continuous integration and delivery (CI/CD) mechanism. The configurations for our workflows can be found in the *.yml files in the .github/workflows directory in the repository root:

  • Continuous Integration: This workflow runs a test job, parametrized across the currently maintained versions of Python, to ensure unit testing passes, and a commits job to ensure we're adhering to the Conventional Commits specification.
  • Semantic Release: This workflow runs on merges to master to automatically generate and publish new releases, based on the commits just merged.

In addition to the GitHub Actions workflows, we also integrate with the following services:

  • Codecov: We calculate and publish code coverage details for all PRs and merged into master, and the service comments on PRs indicating any changes in coverage compared to the base branch.
  • ReadTheDocs: We ensure our documentation builds for all PRs, and the documentation is published for master and all release tags.
  • pre-commit.ci: We ensure all the pre-commit checks we encourage developers to run locally also run in CI.

Merging

When the review is finished and changes are ready to be merged into master:

  1. Rebase your feature branch on top of the latest master.
  2. Clean up your branch with an interactive rebase, squashing down to the smallest number of commits that makes sense. If there are successive distinct changes in a pull request, it's fine for those to be preserved in separate commits.
  3. Notify your reviewers that the request is ready to merge.
  4. Wait for them to merge the request.
  5. Ensure the post-merge CI pipeline also succeeds.

Conventional Comments

When commenting on issues and pull requests, we endeavor to adhere to the Conventional Comments specification wherever applicable. Comments should have the form

<label> [decorations]: <subject>

[discussion]

where:

  • label: This is a single label that signifies what kind of comment is being left.
  • subject: This is the main message of the comment.
  • decorations (optional): These are extra decorating labels for the comment. They are surrounded by parentheses and comma-separated.
  • discussion (optional): This contains supporting statements, context, reasoning, and anything else to help communicate the “why” and “next steps” for resolving the comment.

The labels we use are the following:

  • chore: Chores are simple tasks that must be done before the subject can be “officially” accepted. Usually, these comments reference some common process. Try to leave a link to the process description so that the reader knows how to resolve the chore.
  • issue: Issues highlight specific problems with the subject under review. These problems can be user-facing or behind the scenes. It is strongly recommended to pair this comment with a suggestion. If you are not sure if a problem exists or not, consider leaving a question.
  • note: Notes are always non-blocking and simply highlight something the reader should take note of.
  • polish: Polish comments are like a suggestion, where there is nothing necessarily wrong with the relevant content, there's just some ways to immediately improve the quality.
  • praise: Praises highlight something positive. Try to leave at least one of these comments per review. Do not leave false praise (which can actually be damaging). Do look for something to sincerely praise.
  • quibble: Quibbles are trivial, preference-based requests. These should be non-blocking by nature.
  • suggestion: Suggestions propose improvements to the current subject. It's important to be explicit and clear on what is being suggested and why it is an improvement. Consider using patches and the blocking or non-blocking decorations to further communicate your intent.
  • thought: Thoughts represent an idea that popped up from reviewing. These comments are non-blocking by nature, but they are extremely valuable and can lead to more focused initiatives and mentoring opportunities.
  • todo: TODO's are small, trivial, but necessary changes. Distinguishing todo comments from issues or suggestions helps direct the reader's attention to comments requiring more involvement.
  • typo: Typo comments are like todo, where the main issue is a misspelling.
  • question: Questions are appropriate if you have a potential concern but are not quite sure if it's relevant or not. Asking the author for clarification or investigation can lead to a quick resolution.

The decorations we use are the following:

  • if-minor: This decoration gives some freedom to the author that they should resolve the comment only if the changes ends up being minor or trivial.
  • non-blocking: A comment with this decoration should not prevent the subject under review from being accepted. Without this decoration, comments are assumed to be blocking.