Skip to content

Commit

Permalink
Add Poetry actions (#718)
Browse files Browse the repository at this point in the history
Dupe of #229. Adds poetry Trunk Actions to match parity with
[pre-commit](https://python-poetry.org/docs/pre-commit-hooks/). Note
that the non-hermetic story is much cleaner at time of writing, with the
hermetic story blocked by not being able to unset `VIRTUAL_ENV` in the
Action and Tool. In other words, for now recommended behavior requires
manual [Poetry
installation](https://python-poetry.org/docs/#installation).

We've added a tool test and several actions tests
  • Loading branch information
TylerJang27 authored Mar 27, 2024
1 parent 01640ed commit 3108512
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 10 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,16 +202,17 @@ Enable trunk actions via:
trunk actions enable {action}
```

| action | description |
| -------------------------------------------------------------------- | ---------------------------------------------------------- |
| [`buf-gen`](actions/buf/README.md) | run `buf` on .proto file change |
| [`commitizen`](actions/commitizen/README.md) | enforce conventional commits and manage releases |
| [`commitlint`](https://github.com/conventional-changelog/commitlint) | enforce conventional commit message for your local commits |
| [`go-mod-tidy`](actions/go-mod-tidy/README.md) | automatically tidy go.mod file |
| [`go-mod-tidy-vendor`](actions/go-mod-tidy-vendor/README.md) | automatically tidy and vendor go.mod file |
| [`git-blame-ignore-revs`](actions/git-blame-ignore-revs/README.md) | automatically configure git to use .git-blame-ignore-revs |
| [`npm-check`](actions/npm-check/README.md) | check whether NPM installation is up to date |
| [`yarn-check`](actions/yarn-check/README.md) | check whether Yarn installation is up to date |
| action | description |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| [`buf-gen`](actions/buf/README.md) | run `buf` on .proto file change |
| [`commitizen`](actions/commitizen/README.md) | enforce conventional commits and manage releases |
| [`commitlint`](https://github.com/conventional-changelog/commitlint) | enforce conventional commit message for your local commits |
| [`go-mod-tidy`](actions/go-mod-tidy/README.md) | automatically tidy go.mod file |
| [`go-mod-tidy-vendor`](actions/go-mod-tidy-vendor/README.md) | automatically tidy and vendor go.mod file |
| [`git-blame-ignore-revs`](actions/git-blame-ignore-revs/README.md) | automatically configure git to use .git-blame-ignore-revs |
| [`npm-check`](actions/npm-check/README.md) | check whether NPM installation is up to date |
| [`poetry-check`](actions/poetry/README.md), [`poetry-lock`](actions/poetry/README.md), [`poetry-export`](actions/poetry/README.md), [`poetry-install`](actions/poetry/README.md) | hooks to enforce poetry configuration |
| [`yarn-check`](actions/yarn-check/README.md) | check whether Yarn installation is up to date |

### Supported Tools

Expand Down
52 changes: 52 additions & 0 deletions actions/poetry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Poetry

## Recommended Usage

The recommended way to run [Poetry](https://python-poetry.org/docs/) using Trunk is to use the
SYSTEM environment, rather than a hermetic setup. This is because Poetry provides its own
environment management that will often collide with Trunk's hermetic setup. Nevertheless, leveraging
Poetry and Trunk in parallel can be powerful.

Trunk provides 4 different Actions for running Poetry validation, matching parity with
[Poetry pre-commit hooks](https://python-poetry.org/docs/pre-commit-hooks/).

| action | description |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `poetry-check` | Validate `pyproject.toml` when running `git commit` |
| `poetry-lock` | Update `poetry.lock` to match `pyproject.toml` when running `git commit`. To avoid updating packages, you can override `run` to include `--no-update` |
| `poetry-export` | Update `requirements.txt` to match `pyproject.toml` when running `git commit` |
| `poetry-install` | Install dependencies to make sure all locked packages are installed when running `git checkout` or `git merge` |

You can enable any subset of these Actions using `trunk actions enable`.

As written, all of these actions require that you have `poetry` in your `PATH` in order to run.

## Hermetic Installation

Trunk provides some mechanisms for a hermetic installation and execution of `poetry`. You can use
the Poetry [Tool](https://docs.trunk.io/check/advanced-setup/tools) to run `poetry` manually, and
you can override each of the action definitions to include the `packages_file` and `runtime`, like
so:

```yaml
version: 0.1
actions:
definitions:
- id: poetry-check
runtime: python
packages_file: ${cwd}/requirements.txt
```
These overrides will tell Trunk to use the hermetic install of `poetry` and use a sandboxed
execution for the Action. Note that this approach has some limitations, namely when creating
`poetry` shells or virtual environments. Currently full functionality is blocked by the inability to
unset runtime-inherited environments. Note that the `poetry` Tool suffers from the same problem.

When using the hermetic installation, you will want to ensure that your `python` runtime is enabled
at the same version required by your Poetry configuration. See our
[docs](https://docs.trunk.io/check/advanced-setup/runtimes) for more information about specifying
runtime versions.

## Notes

Poetry requires Python 3.8 or higher to run.
68 changes: 68 additions & 0 deletions actions/poetry/plugin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
version: 0.1
# NOTE: See README.md for usage guidelines.
actions:
definitions:
- id: poetry-check
display_name: poetry check
description: Run 'poetry check' to validate config
# runtime: python
# packages_file: ${cwd}/requirements.txt
run: poetry check
triggers:
- git_hooks: [pre-commit]
environment:
- name: VIRTUAL_ENV
value: ${env.VIRTUAL_ENV}
optional: true

- id: poetry-lock
display_name: poetry lock
# You may wish to override this with 'poetry lock --no-update'
description: Run 'poetry lock' to update lock file to match pyproject.toml
run: poetry lock --no-update
# runtime: python
# packages_file: ${cwd}/requirements.txt
triggers:
- git_hooks: [pre-commit]
environment:
- name: VIRTUAL_ENV
value: ${env.VIRTUAL_ENV}
optional: true

- id: poetry-export
display_name: poetry export
description: Run 'poetry export' to sync requirements.txt with lock file
run: poetry export -f requirements.txt -o requirements.txt
# packages_file: ${cwd}/requirements.txt
# runtime: python
triggers:
- git_hooks: [pre-commit]
environment:
- name: VIRTUAL_ENV
value: ${env.VIRTUAL_ENV}
optional: true

- id: poetry-install
display_name: poetry install
description: Run 'poetry install' to ensure all locked packages are installed
run: poetry install
# packages_file: ${cwd}/requirements.txt
# runtime: python
triggers:
- git_hooks: [post-checkout, post-merge]
environment:
- name: VIRTUAL_ENV
value: ${env.VIRTUAL_ENV}
optional: true

tools:
definitions:
- name: poetry
runtime: python
package: poetry
extra_packages: [poetry-plugin-export]
known_good_version: 1.8.2
health_checks:
- command: poetry --version
parse_regex: ${semver}
shims: [poetry]
103 changes: 103 additions & 0 deletions actions/poetry/poetry.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import * as fs from "fs";
import * as path from "path";
import { actionRunTest, toolInstallTest } from "tests";
import { TrunkActionDriver } from "tests/driver";

toolInstallTest({
toolName: "poetry",
toolVersion: "1.8.2",
});

const preCheck = (authors: boolean) => (driver: TrunkActionDriver) => {
const trunkYamlPath = ".trunk/trunk.yaml";
const currentContents = driver.readFile(trunkYamlPath);
const newContents = currentContents.concat(`
definitions:
- id: poetry-check
runtime: python
packages_file: \${cwd}/requirements.txt
- id: poetry-lock
runtime: python
packages_file: \${cwd}/requirements.txt
- id: poetry-export
runtime: python
packages_file: \${cwd}/requirements.txt`);
driver.writeFile(trunkYamlPath, newContents);

const authorsSection = authors ? "authors = []" : "";
driver.writeFile(
"pyproject.toml",
`[tool.poetry]
name = "poetry-test"
version = "0.1.0"
description = ""
${authorsSection}
[tool.poetry.dependencies]
python = "^3.10"
pendulum = "^3.0.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
`,
);
};

const checkTestCallback = async (driver: TrunkActionDriver) => {
try {
await driver.gitDriver?.commit(
"Test commit",
[],
{ "--allow-empty": null },
(error, result) => {
expect(error?.message).toContain("The fields ['authors'] are required in package mode.");
expect(result).toBeUndefined();
},
);

// Commit step should throw
expect(1).toBe(2);
} catch (_err) {
// Intentionally empty
}
};

const fileExistsCallback = (filename: string) => async (driver: TrunkActionDriver) => {
try {
await driver.gitDriver?.commit(
"Test commit",
[],
{ "--allow-empty": null },
(_error, result) => {
expect(_error).toBeFalsy();
expect(result).toBeTruthy();
},
);

expect(fs.existsSync(path.resolve(driver.getSandbox(), filename))).toBeTruthy();
} catch (_err) {
// Intentionally empty
}
};

actionRunTest({
actionName: "poetry-check",
syncGitHooks: true,
testCallback: checkTestCallback,
preCheck: preCheck(/*authors=*/ false),
});

actionRunTest({
actionName: "poetry-lock",
syncGitHooks: true,
testCallback: fileExistsCallback("poetry.lock"),
preCheck: preCheck(/*authors=*/ true),
});

actionRunTest({
actionName: "poetry-export",
syncGitHooks: true,
testCallback: fileExistsCallback("requirements.txt"),
preCheck: preCheck(/*authors=*/ true),
});
2 changes: 2 additions & 0 deletions actions/poetry/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
poetry==1.8.2
poetry-plugin-export==1.7.1

0 comments on commit 3108512

Please sign in to comment.