ray/ci/README.md

53 lines
2.8 KiB
Markdown
Raw Normal View History

# CI process
_This document is a work-in-progress._
_Please double-check file/function/etc. names for changes, as this document may be out of sync._
### Dependencies
All dependencies (e.g. `apt`, `pip`) should be installed in `install_dependencies()`, following the same pattern as
those that already exist.
2020-05-05 10:47:49 -07:00
Once a dependency is added/removed, please ensure that shell environment variables are persisted appropriately, as CI
systems differ on when `~/.bashrc` et al. are reloaded, if at all. (And they are not necessarily idempotent.)
### Bazel, environment variables, and caching
Any environment variables passed to Bazel actions (e.g. `PATH`) should be idempotent to hit the Bazel cache.
If a different `PATH` gets passed to a Bazel action, Bazel will not hit the cache, and you might trigger a full rebuild
when you really expect an incremental (or no-op) build for an option (say `pip install -e .` after `bazel build //...`).
### Invocation
The CI system (such as Travis) must _source_ (_not_ execute) `ci/travis/ci.sh` and pass the action(s) to execute.
The script either handles the work or dispatches it to other script(s) as it deems appropriate.
This helps ensure any environment setup/teardown is handled appropriately.
### Development best practices & pitfalls (read before adding a new script)
Before adding new scripts, please read this section.
First, please consider modifying an existing script instead (e.g. add your code as a separate function).
Adding new scripts has a number of pitfalls that easily take hours (even days) to track down and fix:
- When _calling_ other scripts (as executables), environment variables (like `PATH`) _cannot_ propagate back up to the
caller. Often, the caller expects such variables to be updated.
- When _sourcing_ other scripts, global state (`ROOT_DIR`, `main`, `set -e`, etc.) may be overwritten silently, causing
unexpected behavior.
The following practices can avoid such pitfalls while maintaining intuitive control flow:
2020-05-05 10:47:49 -07:00
- Put all environment-modifying functions in the _top-level_ shell script, so that their invocation behaves intuitively.
(The sheer length of the script is a secondary concern and can be mitigated by keeping functions modular.)
- Avoid adding new scripts if possible. If it's necessary that you do so, call them instead of sourcing them.
2020-05-05 10:47:49 -07:00
Note that thies implies new scripts should not modify the environment, or the caller will not see such changes!
- Always add code inside a function, not at global scope. Use `local` for variables where it makes sense.
However, be careful and know the shell rules: for example, e.g. `local x=$(false)` succeeds even under `set -e`.
Ultimately, it's best to _only_ add new scripts if they might need to be executed directly by _non-CI_ code,
as in that case, they should probably not use CI entrypoints (which assume exclusive control over the machine).