Skip to content

Commit 5488386

Browse files
authored
Rearrange CONTRIBUTING.md into devdoc chapter and add jldoctests page (#58506)
2 parents 7a87048 + 6fa002d commit 5488386

File tree

9 files changed

+406
-324
lines changed

9 files changed

+406
-324
lines changed

CONTRIBUTING.md

Lines changed: 8 additions & 324 deletions
Large diffs are not rendered by default.

doc/make.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,15 @@ DevDocs = [
279279
"devdocs/build/arm.md",
280280
"devdocs/build/riscv.md",
281281
"devdocs/build/distributing.md",
282+
],
283+
"Contributor's Guide" => [
284+
"devdocs/contributing/code-changes.md",
285+
"devdocs/contributing/tests.md",
286+
"devdocs/contributing/documentation.md",
287+
"devdocs/contributing/jldoctests.md",
288+
"devdocs/contributing/patch-releases.md",
289+
"devdocs/contributing/formatting.md",
290+
"devdocs/contributing/git-workflow.md",
282291
]
283292
]
284293

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
### Contributing to core functionality or base libraries
2+
3+
*By contributing code to Julia, you are agreeing to release it under the [MIT License](https://github.com/JuliaLang/julia/tree/master/LICENSE.md).*
4+
5+
The Julia community uses [GitHub issues](https://github.com/JuliaLang/julia/issues) to track and discuss problems, feature requests, and pull requests (PR).
6+
7+
Issues and pull requests should have self explanatory titles such that they can be understood from the list of PRs and Issues.
8+
i.e. `Add {feature}` and `Fix {bug}` are good, `Fix #12345. Corrects the bug.` is bad.
9+
10+
You can make pull requests for incomplete features to get code review. The convention is to open these as draft PRs and prefix
11+
the pull request title with "WIP:" for Work In Progress, or "RFC:" for Request for Comments when work is completed and ready
12+
for merging. This will prevent accidental merging of work that is in progress.
13+
14+
Note: These instructions are for adding to or improving functionality in the base library. Before getting started, it can be helpful to discuss the proposed changes or additions on the [Julia Discourse forum](https://discourse.julialang.org) or in a GitHub issue---it's possible your proposed change belongs in a package rather than the core language. Also, keep in mind that changing stuff in the base can potentially break a lot of things. Finally, because of the time required to build Julia, note that it's usually faster to develop your code in stand-alone files, get it working, and then migrate it into the base libraries.
15+
16+
Add new code to Julia's base libraries as follows (this is the "basic" approach; see a more efficient approach in the next section):
17+
18+
1. Edit the appropriate file in the `base/` directory, or add new files if necessary. Create tests for your functionality and add them to files in the `test/` directory. If you're editing C or Scheme code, most likely it lives in `src/` or one of its subdirectories, although some aspects of Julia's REPL initialization live in `cli/`.
19+
20+
2. Add any new files to `sysimg.jl` in order to build them into the Julia system image.
21+
22+
3. Add any necessary export symbols in `exports.jl`.
23+
24+
4. Include your tests in `test/Makefile` and `test/choosetests.jl`.
25+
26+
Build as usual, and do `make clean testall` to test your contribution. If your contribution includes changes to Makefiles or external dependencies, make sure you can build Julia from a clean tree using `git clean -fdx` or equivalent (be careful – this command will delete any files lying around that aren't checked into git).
27+
28+
#### Running specific tests
29+
30+
There are `make` targets for running specific tests:
31+
32+
make test-bitarray
33+
34+
You can also use the `runtests.jl` script, e.g. to run `test/bitarray.jl` and `test/math.jl`:
35+
36+
./usr/bin/julia test/runtests.jl bitarray math
37+
38+
#### Modifying base more efficiently with Revise.jl
39+
40+
[Revise](https://github.com/timholy/Revise.jl) is a package that
41+
tracks changes in source files and automatically updates function
42+
definitions in your running Julia session. Using it, you can make
43+
extensive changes to Base without needing to rebuild in order to test
44+
your changes.
45+
46+
Here is the standard procedure:
47+
48+
1. If you are planning changes to any types or macros, make those
49+
changes and build julia using `make`. (This is
50+
necessary because `Revise` cannot handle changes to type
51+
definitions or macros.) Unless it's
52+
required to get Julia to build, you do not have to add any
53+
functionality based on the new types, just the type definitions
54+
themselves.
55+
56+
2. Start a Julia REPL session. Then issue the following commands:
57+
58+
```julia
59+
using Revise # if you aren't launching it in your `.julia/config/startup.jl`
60+
Revise.track(Base)
61+
```
62+
63+
3. Edit files in `base/`, save your edits, and test the
64+
functionality.
65+
66+
If you need to restart your Julia session, just start at step 2 above.
67+
`Revise.track(Base)` will note any changes from when Julia was last
68+
built and incorporate them automatically. You only need to rebuild
69+
Julia if you made code-changes that Revise cannot handle.
70+
71+
For convenience, there are also `test-revise-*` targets for every [`test-*`
72+
target](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md#running-specific-tests) that use Revise to load any modifications to Base into the current
73+
system image before running the corresponding test. This can be useful as a shortcut
74+
on the command line (since tests aren't always designed to be run outside the
75+
runtest harness).
76+
77+
### Contributing to the standard library
78+
79+
The standard library (stdlib) packages are baked into the Julia system image.
80+
When running the ordinary test workflow on the stdlib packages, the system image
81+
version overrides the version you are developing.
82+
To test stdlib packages, you can do the following steps:
83+
84+
1. Edit the UUID field of the `Project.toml` in the stdlib package
85+
2. Change the current directory to the directory of the stdlib you are developing
86+
3. Start julia with `julia --project=.`
87+
4. You can now test the package by running `pkg> test` in Pkg mode.
88+
89+
Because you changed the UUID, the package manager treats the stdlib package as
90+
different from the one in the system image, and the system image version will
91+
not override the package.
92+
93+
Be sure to change the UUID value back before making the pull request.
94+
95+
#### News-worthy changes
96+
97+
For new functionality and other substantial changes, add a brief summary to `NEWS.md`. The news item should cross reference the pull request (PR) parenthetically, in the form `([#pr])`. To add the PR reference number, first create the PR, then push an additional commit updating `NEWS.md` with the PR reference number. We periodically run `./julia doc/NEWS-update.jl` from the julia directory to update the cross-reference links, but this should not be done in a typical PR in order to avoid conflicting commits.
98+
99+
#### Annotations for new features, deprecations and behavior changes
100+
101+
API additions and deprecations, and minor behavior changes are allowed in minor version releases.
102+
For documented features that are part of the public API, a compatibility note should be added into
103+
the manual or the docstring. It should state the Julia minor version that changed the behavior
104+
and have a brief message describing the change.
105+
106+
At the moment, this should always be done with the following `compat` admonition
107+
(so that it would be possible to programmatically find the annotations in the future):
108+
109+
```
110+
!!! compat "Julia 1.X"
111+
This method was added in Julia 1.X.
112+
```
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
### Improving documentation
2+
3+
*By contributing documentation to Julia, you are agreeing to release it under the [MIT License](https://github.com/JuliaLang/julia/tree/master/LICENSE.md).*
4+
5+
Julia's documentation source files are stored in the `doc/` directory and all docstrings are found in `base/`. Like everything else these can be modified using `git`. Documentation is built with [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl), which uses Markdown syntax. The HTML documentation can be built locally by running
6+
7+
```
8+
make docs
9+
```
10+
11+
from Julia's root directory. This will rebuild the Julia system image, then install or update the package dependencies required to build the documentation, and finally build the HTML documentation and place the resulting files in `doc/_build/html/`.
12+
13+
> **Note**
14+
>
15+
> When making changes to any of Julia's documentation it is recommended that you run `make docs` to check that your changes are valid and do not produce any errors before opening a pull request.
16+
17+
Below are outlined the three most common types of documentation changes and the steps required to perform them. Please note that the following instructions do not cover the full range of features provided by Documenter.jl. Refer to [Documenter's documentation](https://juliadocs.github.io/Documenter.jl/stable) if you encounter anything that is not covered by the sections below.
18+
19+
#### Modifying files in `doc/src/`
20+
21+
Most of the source text for the Julia Manual is located in `doc/src/`. To update or add new text to any one of the existing files the following steps should be followed:
22+
23+
1. update the text in whichever `.md` files are applicable;
24+
2. run `make docs` from the root directory;
25+
3. check the output in `doc/_build/html/` to make sure the changes are correct;
26+
4. commit your changes and open a pull request.
27+
28+
> **Note**
29+
>
30+
> The contents of `doc/_build/` does **not** need to be committed when you make changes.
31+
32+
To add a **new file** to `doc/src/` rather than updating a file replace step `1` above with
33+
34+
1. add the file to the appropriate subdirectory in `doc/src/` and also add the file path to the `PAGES` vector in `doc/make.jl`.
35+
36+
#### Modifying an existing docstring in `base/`
37+
38+
All docstrings are written inline above the methods or types they are associated with and can be found by clicking on the `source` link that appears below each docstring in the HTML file. The steps needed to make a change to an existing docstring are listed below:
39+
40+
1. find the docstring in `base/`;
41+
2. update the text in the docstring;
42+
3. run `make docs` from the root directory;
43+
4. check the output in `doc/_build/html/` to make sure the changes are correct;
44+
5. commit your changes and open a pull request.
45+
46+
#### Adding a new docstring to `base/`
47+
48+
The steps required to add a new docstring are listed below:
49+
50+
1. find a suitable definition in `base/` that the docstring will be most applicable to;
51+
2. add a docstring above the definition;
52+
3. find a suitable `@docs` code block in one of the `doc/src/stdlib/` files where you would like the docstring to appear;
53+
4. add the name of the definition to the `@docs` code block. For example, with a docstring added to a function `bar`
54+
55+
```julia
56+
"..."
57+
function bar(args...)
58+
# ...
59+
end
60+
```
61+
62+
you would add the name `bar` to a `@docs` block in `doc/src/stdlib/`
63+
64+
```@docs
65+
foo
66+
bar # <-- Added this one.
67+
baz
68+
```
69+
70+
5. run `make docs` from the root directory;
71+
6. check the output in `doc/_build/html` to make sure the changes are correct;
72+
7. commit your changes and open a pull request.
73+
74+
#### Doctests
75+
76+
Examples written within docstrings can be used as testcases known as "doctests" by annotating code blocks with `jldoctest`.
77+
78+
```jldoctest
79+
julia> uppercase("Docstring test")
80+
"DOCSTRING TEST"
81+
```
82+
83+
A doctest needs to match an interactive REPL including the `julia>` prompt. It is recommended to add the header `# Examples` above the doctests.
84+
85+
See the documentation of [writing jldoctests](@ref writing-jldoctests) for best
86+
practices on how to write doctests for common scenarios and the `doc/README.md`
87+
file for how to run the doctests.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
### Code Formatting Guidelines
2+
3+
#### General Formatting Guidelines for Julia code contributions
4+
5+
- Follow the latest dev version of [Julia Style Guide](https://docs.julialang.org/en/v1/manual/style-guide/).
6+
- use whitespace to make the code more readable
7+
- no whitespace at the end of a line (trailing whitespace)
8+
- comments are good, especially when they explain the algorithm
9+
- try to adhere to a 92 character line length limit
10+
- it is generally preferred to use ASCII operators and identifiers over
11+
Unicode equivalents whenever possible
12+
- in docstrings refer to the language as "Julia" and the executable as "`julia`"
13+
14+
#### General Formatting Guidelines For C code contributions
15+
16+
- 4 spaces per indentation level, no tabs
17+
- space between `if` and `(` (`if (x) ...`)
18+
- newline before opening `{` in function definitions
19+
- `f(void)` for 0-argument function declarations
20+
- newline between `}` and `else` instead of `} else {`
21+
- if one part of an `if..else` chain uses `{ }` then all should
22+
- no whitespace at the end of a line
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Git workflow recommendations
2+
3+
### Git Recommendations For Pull Requests
4+
5+
- Avoid working from the `master` branch of your fork. Create a new branch as it will make it easier to update your pull request if Julia's `master` changes.
6+
- Try to [squash](https://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) together small commits that make repeated changes to the same section of code, so your pull request is easier to review. A reasonable number of separate well-factored commits is fine, especially for larger changes.
7+
- If any conflicts arise due to changes in Julia's `master`, prefer updating your pull request branch with `git rebase` versus `git merge` or `git pull`, since the latter will introduce merge commits that clutter the git history with noise that makes your changes more difficult to review.
8+
- Descriptive commit messages are good.
9+
- Using `git add -p` or `git add -i` can be useful to avoid accidentally committing unrelated changes.
10+
- When linking to specific lines of code in discussion of an issue or pull request, hit the `y` key while viewing code on GitHub to reload the page with a URL that includes the specific version that you're viewing. That way any lines of code that you refer to will still make sense in the future, even if the content of the file changes.
11+
- Whitespace can be automatically removed from existing commits with `git rebase`.
12+
- To remove whitespace for the previous commit, run
13+
`git rebase --whitespace=fix HEAD~1`.
14+
- To remove whitespace relative to the `master` branch, run
15+
`git rebase --whitespace=fix master`.
16+
17+
#### Git Recommendations For Pull Request Reviewers
18+
19+
- When merging, we generally like `squash+merge`. Unless it is the rare case of a PR with carefully staged individual commits that you want in the history separately, in which case `merge` is acceptable, but usually prefer `squash+merge`.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# [Writing jldoctests](@id writing-jldoctests)
2+
3+
This page describes how to write and maintain `jldoctest` blocks in the documentation. Following these guidelines helps keep doctests reliable and easy to read.
4+
5+
## Filters
6+
7+
Use `filter =` whenever output contains text that might vary across runs.
8+
The documentation relies on several recurring patterns:
9+
10+
- `r"int.jl:\\d+"` — remove line numbers from introspection macros.
11+
- `r"Stacktrace:(\\n \\[0-9]+\\].*)*"` — hide stack traces when illustrating
12+
errors.
13+
- `r"Closest candidates.*\\n .*"` — skip the method suggestions printed by
14+
`MethodError`.
15+
- `r"@ .*"` — strip file locations from the output of `methods` or
16+
`@which`.
17+
- `r"\\@world\\(MyStruct, \\d+:\\d+\\)"` — filter world age numbers.
18+
- `r"with \\d+ methods"` — ignore method counts when redefining functions.
19+
- `r"[0-9\\.]+ seconds \\(.*?\\)"` — remove timing output with memory
20+
information.
21+
- `r"[0-9\\.]+ seconds"` — remove simple timing results.
22+
- `r"[0-9\\.]+"` — filter digits from names such as anonymous functions.
23+
- `r"([A-B] [0-5])"` and `r"[A-B] [X-Z] [0-5]"` — account for non-deterministic
24+
process output.
25+
- `r"(world\\nhello|hello\\nworld)"` — allow either ordering of interleaved
26+
output.
27+
28+
If none of these match your situation, craft a regular expression that
29+
removes the varying text. Using filters keeps doctests stable across
30+
platforms and Julia versions.
31+
32+
## Setup code
33+
34+
Small setup expressions may be placed inline using the `setup =` option:
35+
36+
````
37+
```jldoctest; setup = :(using InteractiveUtils)
38+
...
39+
```
40+
````
41+
42+
For longer setup code or if multiple blocks require the same environment, use the
43+
`DocTestSetup` meta block:
44+
45+
````
46+
```@meta
47+
DocTestSetup = :(import Random; Random.seed!(1234))
48+
```
49+
````
50+
51+
and disable it afterwards with
52+
53+
````
54+
```@meta
55+
DocTestSetup = nothing
56+
```
57+
````
58+
59+
## Maintaining state between snippets
60+
61+
Related doctest blocks can share state by giving them the same label after the
62+
`jldoctest` keyword. The manual uses this pattern to demonstrate mutation:
63+
64+
````
65+
```jldoctest mutation_vs_rebind
66+
julia> a = [1,2,3]
67+
...
68+
```
69+
````
70+
71+
and later
72+
73+
````
74+
```jldoctest mutation_vs_rebind
75+
julia> a[1] = 42
76+
...
77+
```
78+
````
79+
80+
Blocks with the same name execute sequentially during doctesting, so variables
81+
created in the first block remain available in the following ones.
82+
83+
When a snippet needs to preserve its result for later examples, give it a label
84+
and reuse that label. This avoids repeating setup code and mirrors a REPL
85+
session more closely.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
### Contributing to patch releases
3+
4+
The process of [creating a patch release](https://docs.julialang.org/en/v1/devdocs/build/distributing/#Point-releasing-101) is roughly as follows:
5+
6+
1. Create a new branch (e.g. `backports-release-1.10`) against the relevant minor release
7+
branch (e.g. `release-1.10`). Usually a corresponding pull request is created as well.
8+
9+
2. Add commits, nominally from `master` (hence "backports"), to that branch.
10+
See below for more information on this process.
11+
12+
3. Run the [BaseBenchmarks.jl](https://github.com/JuliaCI/BaseBenchmarks.jl) benchmark
13+
suite and [PkgEval.jl](https://github.com/JuliaCI/PkgEval.jl) package ecosystem
14+
exerciser against that branch. Nominally BaseBenchmarks.jl and PkgEval.jl are
15+
invoked via [Nanosoldier.jl](https://github.com/JuliaCI/Nanosoldier.jl) from
16+
the pull request associated with the backports branch. Fix any issues.
17+
18+
4. Once all test and benchmark reports look good, merge the backports branch into
19+
the corresponding release branch (e.g. merge `backports-release-1.10` into
20+
`release-1.10`).
21+
22+
5. Open a pull request that bumps the version of the relevant minor release to the
23+
next patch version, e.g. as in [this pull request](https://github.com/JuliaLang/julia/pull/37718).
24+
25+
6. Ping `@JuliaLang/releases` to tag the patch release and update the website.
26+
27+
7. Open a pull request that bumps the version of the relevant minor release to the
28+
next prerelease patch version, e.g. as in [this pull request](https://github.com/JuliaLang/julia/pull/37724).
29+
30+
Step 2 above, i.e. backporting commits to the `backports-release-X.Y` branch, has largely
31+
been automated via [`Backporter`](https://github.com/KristofferC/Backporter): Backporter
32+
searches for merged pull requests with the relevant `backport-X.Y` tag, and attempts to
33+
cherry-pick the commits from those pull requests onto the `backports-release-X.Y` branch.
34+
Some commits apply successfully without intervention, others not so much. The latter
35+
commits require "manual" backporting, with which help is generally much appreciated.
36+
Backporter generates a report identifying those commits it managed to backport automatically
37+
and those that require manual backporting; this report is usually copied into the first
38+
post of the pull request associated with `backports-release-X.Y` and maintained as
39+
additional commits are automatically and/or manually backported.
40+
41+
When contributing a manual backport, if you have the necessary permissions, please push the
42+
backport directly to the `backports-release-X.Y` branch. If you lack the relevant
43+
permissions, please open a pull request against the `backports-release-X.Y` branch with the
44+
manual backport. Once the manual backport is live on the `backports-release-X.Y` branch,
45+
please remove the `backport-X.Y` tag from the originating pull request for the commits.

0 commit comments

Comments
 (0)