|
1 |
| -# Contributing to `gdext` |
| 1 | +# Contributing to gdext |
2 | 2 |
|
3 |
| -At this stage, we appreciate if users experiment with the library, use it in small projects and report issues and bugs they encounter. |
| 3 | +We appreciate if users experiment with the library, use it in small projects and report issues they encounter. |
| 4 | +If you intend to contribute code, please read the section _Pull request guidelines_ below, so you spend less time on administrative tasks. |
4 | 5 |
|
5 |
| -If you plan to make bigger contributions, make sure to discuss them in a [GitHub issue] first. Since the library is evolving quickly, this avoids that multiple people work on the same thing or implement features in a way that doesn't work with other parts. Also don't hesitate to talk to the developers in the `#contrib-gdext` channel on [Discord]! |
| 6 | +The rest of the document goes into tools and infrastructure available for development. |
6 | 7 |
|
7 |
| -## Check script |
8 | 8 |
|
9 |
| -The script `check.sh` in the project root can be used to mimic a CI run locally. It's useful to run this before you commit, push or create a pull request: |
| 9 | +## Pull request guidelines |
10 | 10 |
|
11 |
| -``` |
12 |
| -$ check.sh |
| 11 | +### Larger changes need design |
| 12 | + |
| 13 | +If you plan to make bigger contributions, make sure to discuss them in a [GitHub issue] before opening a pull request (PR). |
| 14 | +Since the library is evolving quickly, this avoids that multiple people work on the same thing, or that features don't integrate well, |
| 15 | +causing a lot of rework. Also don't hesitate to talk to the developers in the `#contrib-gdext` channel on [Discord]! |
| 16 | + |
| 17 | + |
| 18 | +### One commit per logical change |
| 19 | + |
| 20 | +This makes it easier to review changes, later reconstruct what happened when and -- in case of regressions -- revert individual commits. |
| 21 | +The exception are tiny changes of a few lines that don't bear semantic significance (typos, style, etc.). |
| 22 | +Larger code style changes should be split though. |
| 23 | + |
| 24 | +If your pull request changes a single thing, please squash the commits into one. Avoid commits like "integrate review feedback" or "fix rustfmt". |
| 25 | +Instead, use `git commit --amend` or `git rebase -i` and force-push follow-up commits to your branch (`git push --force-with-lease`). |
| 26 | +Since we use the _bors_ bot to merge PRs, we can unfortunately not squash commits upon merge. |
| 27 | + |
| 28 | + |
| 29 | +### Draft PRs |
| 30 | + |
| 31 | +In case you plan to work for a longer time on a feature/bugfix, consider opening a PR as a draft. |
| 32 | +This signals that reviews are appreciated, but that the code is not yet ready for merge. |
| 33 | +Non-draft PRs that pass CI are assumed to be mergeable (and maintainers may do so). |
| 34 | +<br/> |
| 35 | + |
| 36 | +# Dev tools |
| 37 | + |
| 38 | +## Local development |
| 39 | + |
| 40 | +The script `check.sh` in the project root can be used to mimic a minimal version of CI locally. |
| 41 | +It's useful to run this before you commit, push or create a pull request: |
| 42 | + |
| 43 | +```bash |
| 44 | +$ ./check.sh |
13 | 45 | ```
|
14 | 46 |
|
15 |
| -At the time of writing, this will run formatting, clippy, unit tests and integration tests. More checks may be added in the future. Run `./check.sh --help` to see all available options. |
| 47 | +At the time of writing, this will run formatting, clippy, unit tests and integration tests. More checks may be added in the future. |
| 48 | +Run `./check.sh --help` to see all available options. |
16 | 49 |
|
17 | 50 | If you like, you can set this as a pre-commit hook in your local clone of the repository:
|
18 | 51 |
|
19 |
| -``` |
| 52 | +```bash |
20 | 53 | $ ln -sf check.sh .git/hooks/pre-commit
|
21 | 54 | ```
|
22 | 55 |
|
23 |
| -## Unit tests |
24 | 56 |
|
25 |
| -Because most of `gdext` interacts with the Godot engine, which is not available from the test executable, unit tests (using `cargo test` and the `#[test]` attribute) are pretty limited in scope. |
| 57 | +### Unit tests |
26 | 58 |
|
27 |
| -Because additional flags might be needed, the preferred way to run unit tests is through the `check.sh` script: |
| 59 | +Because most of gdext interacts with the Godot engine, which is not available from the test executable, unit tests |
| 60 | +(using `cargo test` and the `#[test]` attribute) are pretty limited in scope. They are primarily used for Rust-only logic. |
28 | 61 |
|
29 |
| -``` |
| 62 | +As additional flags might be needed, the preferred way to run unit tests is through the `check.sh` script: |
| 63 | + |
| 64 | +```bash |
30 | 65 | $ ./check.sh test
|
31 | 66 | ```
|
32 | 67 |
|
33 |
| -## Integration tests |
34 |
| - |
35 |
| -The `itest/` directory contains a suite of integration tests that actually exercise `gdext` from within Godot. |
36 | 68 |
|
37 |
| -The `itest/rust` directory is a Rust `cdylib` library project that can be loaded as a GDExtension in Godot, with an entry point for running integration tests. The `itest/godot` directory contains the Godot project that loads this library and invokes the test suite. |
| 69 | +### Integration tests |
| 70 | + |
| 71 | +The `itest` directory contains a suite of integration tests. It is split into two directories: |
| 72 | +`rust`, containing the Rust code for the GDExtension library, and `godot` with the Godot project and GDScript tests. |
| 73 | + |
| 74 | +Similar to `#[test]`, the function annotated by `#[itest]` contains one integration test. There are multiple syntax variations: |
| 75 | + |
| 76 | +```rust |
| 77 | +// Use a Godot API and verify the results using assertions. |
| 78 | +#[itest] |
| 79 | +fn variant_nil() { |
| 80 | + let variant = Variant::nil(); |
| 81 | + assert!(variant.is_nil()); |
| 82 | +} |
| 83 | + |
| 84 | +// TestContext parameter gives access to a node in the scene tree. |
| 85 | +#[itest] |
| 86 | +fn do_sth_with_the_tree(ctx: &TestContext) { |
| 87 | + let tree: Gd<Node> = ctx.scene_tree.share(); |
| 88 | + |
| 89 | + // If you don't need the scene, you can also construct free-standing nodes: |
| 90 | + let node: Gd<Node3D> = Node3D::new_alloc(); |
| 91 | + // ... |
| 92 | + node.free(); // don't forget to free everything created by new_alloc(). |
| 93 | +} |
| 94 | + |
| 95 | +// Skip a test that's not yet ready. |
| 96 | +#[itest(skip)] |
| 97 | +fn not_executed() { |
| 98 | + // ... |
| 99 | +} |
| 100 | + |
| 101 | +// Focus on a one or a few tests. |
| 102 | +// As soon as there is at least one #[itest(focus)], only focused tests are run. |
| 103 | +#[itest(focus)] |
| 104 | +fn i_need_to_debug_this() { |
| 105 | + // ... |
| 106 | +} |
| 107 | +``` |
38 | 108 |
|
39 | 109 | You can run the integration tests like this:
|
40 | 110 |
|
41 |
| -``` |
| 111 | +```bash |
42 | 112 | $ ./check.sh itest
|
43 | 113 | ```
|
44 | 114 |
|
45 | 115 | Just like when compiling the crate, the `GODOT4_BIN` environment variable can be used to supply the path and filename of your Godot executable.
|
| 116 | +Otherwise, a binary named `godot4` in your PATH is used. |
| 117 | + |
46 | 118 |
|
47 |
| -## Formatting |
| 119 | +### Formatting |
48 | 120 |
|
49 | 121 | `rustfmt` is used to format code. `check.sh` only warns about formatting issues, but does not fix them. To do that, run:
|
50 | 122 |
|
51 |
| -``` |
| 123 | +```bash |
52 | 124 | $ cargo fmt
|
53 | 125 | ```
|
54 | 126 |
|
55 |
| -## Clippy |
| 127 | + |
| 128 | +### Clippy |
56 | 129 |
|
57 | 130 | `clippy` is used for additional lint warnings not implemented in `rustc`. This, too, is best run through `check.sh`:
|
58 | 131 |
|
| 132 | +```bash |
| 133 | +$ ./check.sh clippy |
59 | 134 | ```
|
60 |
| -$ check.sh clippy |
| 135 | + |
| 136 | +## Continuous Integration |
| 137 | + |
| 138 | +If you want to have the full CI experience, you can experiment as much as you like on your own gdext fork, before submitting a pull request. |
| 139 | + |
| 140 | +For this, navigate to the file `.github/workflows/full-ci.yml` and change the following lines: |
| 141 | + |
| 142 | +```yml |
| 143 | +on: |
| 144 | + push: |
| 145 | + branches: |
| 146 | + - staging |
| 147 | + - trying |
61 | 148 | ```
|
62 | 149 |
|
63 |
| -## Real |
| 150 | +to: |
| 151 | +
|
| 152 | +```yml |
| 153 | +on: |
| 154 | + push: |
| 155 | +``` |
| 156 | +
|
| 157 | +This runs the entire CI pipeline to run on every push. You can then see the results in the _Actions_ tab in your repository. |
| 158 | +
|
| 159 | +Don't forget to undo this before opening a PR! You may want to keep it in a separate commit named "UNDO" or similar. |
64 | 160 |
|
65 |
| -Certain types in Godot use either a single or double-precision float internally, such as `Vector2`. When using these types we |
66 |
| -use the `real` type instead of choosing either `f32` or `f64`. Thus our code is portable between Godot binaries compiled with |
67 |
| -`precision=single` or `precision=double`. |
| 161 | +
|
| 162 | +## Build configurations |
| 163 | +
|
| 164 | +### `real` type |
| 165 | + |
| 166 | +Certain types in Godot use either a single or double-precision float internally, such as `Vector2`. |
| 167 | +When working with these types, we use the `real` type instead of choosing either `f32` or `f64`. |
| 168 | +As a result, our code is portable between Godot binaries compiled with `precision=single` and `precision=double`. |
68 | 169 |
|
69 | 170 | To run the testing suite with `double-precision` enabled you may add `--double` to a `check.sh` invocation:
|
70 |
| -``` |
71 |
| -$ check.sh --double |
| 171 | +```bash |
| 172 | +$ ./check.sh --double |
72 | 173 | ```
|
73 | 174 |
|
74 | 175 | [GitHub issue]: https://github.com/godot-rust/gdext/issues
|
|
0 commit comments