Contributions of all kinds are welcome. For new features, please open an issue to discuss first.
Conventional commits are used.
Not all commits require a convention, but in general a user-facing change should include at least
one commit with either a fix: or feat: commit, so that the compiler version is bumped correctly.
Other conventions such as docs: or test: are not necessarily required but may be helpful to
see when reviewing.
Ensure to describe the changes made in a scriv fragment file which can be generated by running scriv create command. The fragment file is then generated in changelog.d folder and contains all the types recognised by Conventional commits. Uncomment the sections relevant to the changes being made and fill in the details. The file should be commited and be part of the pull request.
The fragment file is deleted by the CD pipeline once it is integrated into CHANGELOG.md file as part of CD process.
The codebase has approval tests that can be used to see diffs on generated outputs from each compiler layer. This is a really useful mechanism to protect against regressions and understand the effect of a change to the compiler, but also can result in a huge amount of noise. For this reason some thought should be given to how the commits in a PR are arranged. It is recommended when making changes that affect compiler output to have two commits, one with the code change and a second with the relevant approval changes. Avoid having approval commits that mix two different types of changes, for example. If a change affects all files but has no significant impact (e.g. a formatting change), it should not be combined with another change that is significant (e.g. a bug fix, or new optimization)
a PR separating significant changes from insignificant change may look like the following
- refactor: add additional indentation to IR output
- chore: compile all
- feat: added a new IR optimization
- chore: compile all
Pull Requests involving the TEAL layer (src/puya/teal) require the approval of two or more reviewers before merging.
- Ensure uv is installed.
- Clone the repository locally.
- You can create the virtual env and install dependencies with
uv syncin a terminal, or use the IDE integration. - For more on using the virtual env from the command line see the uv docs
- Optionally debug individual tests
- Run
algokit localnet start - Use your IDEs built-in run/debug setup to run tests (via pytest)
- Run
uv is used for virtual environment and dependency management.
Dependencies for building docs are in a separate docs dependency group, this is only required
if you want to build the documentation locally to see the effects of any edits you made.
poe is used for running various scripts/commands used in local development.
ruff is used for linting and formatting, mypy is used for static analysis. pre-commit is
configured, so you will want to either install the hooks with pre-commit install or you can run
things manually via poe lint.
poe compile_all_fast can be run to update all compiler approvals output by running the test_compile suite
Approvals output can often result in conflicts when rebasing or merging branches.
Generally the best strategy to resolve this is to accept the original set of changes and then
rerun poe compile_all_fast to update the approvals with the cumulative changes.
To assist with this the merge driver for approvals output (defined in .gitattributes with merge=theirs)
can be defined with git config merge.theirs.driver true which will config git to automatically accept "theirs" for these files.
Testing uses pytest. You'll need to have a local algod node running for most of the tests
to run, see algokit-cli.
Part of the tests include checking for no output changes to examples/ or test_cases/. If there
are deliberate changes, you should commit those for the tests to pass.
The Puya compiler needs some additional information about AVM ops (such as op code values and application modes) that the langspec in the official go-alogrand repo does not provide. As such we have a branch of go-algorand with some minimal adjustments to the langspec generation code to add the required info. The following steps describe the current process to update the langspec used in the Puya compiler
- Checkout https://github.com/daniel-makerx/go-algorand and then
- Switch to
op-specbranch, the branch will need to be rebased onto master and updated for any relevant changes. However initially it is recommended to follow the remaining steps first to ensure the process is working Things that may require updating after rebasing: _ update any new FieldSpec types indata/transactions/logic/fields.goby adding a Modes() function. This will typically cause amake buildto fail if not done. _ updatecmd/opdoc/opdoc.go:argEnums()to include any new enums. This will typically cause an error when running thepoe genstep when not done. * updatecmd/opdoc/opdoc.go:main()with the desired version, typically for Puya we want this to be the next unreleased version. - Install Go. (Also ensure
$GOPATH$/binenvironment variable is included on your path as some build tools are installed here) - Execute the following scripts as per the Initial Environment Setup in the README.md
./scripts/configure_dev.sh./scripts/buildtools/install_buildtools.sh - Execute
make buildin the repository root - Execute
make README.mdin thedata/transactions/logicdirectory. This will produce a langspec and markdown file for each version - Copy the latest langspec into the Puya repository e.g.
cp langspec_v12.json ~/repos/algorand/puya/langspec.json
- Switch to
- Then within the Puya project
- Run
poe gento update all generated files derived from the langspec - Update
src/puya/algo_constants.py:SUPPORTED_AVM_VERSIONSas appropriate - Add relevant test cases for new ops
- Bump the algopy-stubs version as appropriate (typically this would just be a minor version bump)
- Run