Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Poetry actions #229

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 run validate poetry setup |
| [`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
Loading