Contributing to Fallout
January 10, 2022 ยท View on GitHub
Architecture
If you want to understand the internals of the queueing and running mechanism, there's a class collaboration sketch here; there's also a collaboration sketch for the LiveLog here.
There is also a sequence diagram to show how the separate QUEUE and RUNNER processes interact here.
All of the above diagrams are generated from .dot/.plantuml files in docs/assets by the gradle docs task.
Making Changes
Common Gotchas
-
When adding
PropertySpecs to a component, make sure they're returned ingetPropertySpecs(). -
When writing code that needs the IP of a
Node, prefer usingUtils.getContactPoints()to get the appropriate IP addresses, as this will correctly give you the private or public IP to use, instead of usingNode.getPublic/PrivateAddressdirectly. -
When writing a
Module.runmethod that doesn't just run something viaNode.execute()(the abort mechanism will handle this for you), consider making it periodically checkModule.isTestRunAbortedso that it can be aborted. -
If you need to wait on the results of several
Node.execute()commands on multiple nodes, use theUtils.waitFor*methods; -
The following
NodeResponsemethods can block until a process has started (depending on the Provisioner in use, this may be a non-trivial amount of time):getOutputStream,getErrorStream,getExitCode. You shouldn't need to call the first two, and you should only callgetExitCodeafter a NodeResponseisCompleted(calling it before can raise an exception, depending on the Provisioner in use). Rather than calling these methods directly, use theNodeResponseandUtilswaitFor*methods to log output and check for completion.
Code Style
This is enforced by spotless and ktlint, with the settings held in .editorconfig for ktlint, and in the spotless config blocks in build.gradle in fallout-oss and fallout-ds, which in turn import eclipse-format.prefs.
See the code style section under Using IntelliJ IDEA for how to make IDEA auto-format using the above settings.
Assertions
Please do not use raw Java assert; use the methods provided by Guava's Verify and Preconditions in production code, and use AssertJ's assertThat in test code:
- In production code:
- Use
Verify.verifyandverifyNotNull. - Bonus points: if you have something that is unambiguously a precondition, then feel free to use
Preconditions.checkArgument/checkState/checkNotNull. Hint: it's not a precondition if it's not at the beginning of a method. But really,Verifyis fine.
- Use
- If you're writing a test:
- Use
AssertJ'sassertThat(note this is not theassertThatfrom junit).
- Use
Submitting Code
- Make sure you run
./gradlew lintto make sure your code at least compiles and passes style checks before pushing (the git hooks described below will do this for you).- If the
spotlessCheckorktlinttasks in any of the projects fail, the error message will tell you what task to run to fix the problem.
- If the
- Submit change requests via the Github Pull Request workflow.
- GitHub Actions will build and test your branch.
Git hooks
Some useful git hooks will be installed by running ./gradlew setupGit (you can safely run this as many times as you like); to get the full advantage of these, you should install shellcheck. The shellcheck is not currently enforced by CI, but everything else is; if you have modified something that wasn't already shellcheck-clean, and you just want to check it in, use the --no-verify flag with git commit.
To prevent leaking secrets, the setupGit task will also run git secrets to configure a default set of patterns. If you haven't already installed git-secrets then you should do so, and run setupGit again.
Reviewing
All PRs need a reviewer's +1.
Delivering PRs
-
If your change is a single commit, or multiple commits that you don't think are worth keeping in the history, please squash-and-merge.
-
If your change is multiple commits and you do think they're worth keeping in the history, please perform a plain merge.
-
If you have a separate commit with a failing test because you've TDD'd the solution into existence, please squash the failing test into a commit where it passes (there should be no intentional commits that fail test, since this makes bisecting impossible).
-
Note that rebase-and-merge is disabled on the fallout GH repo; the rationale is that there's no option to put in a sensible commit message, and the commits can't easily be traced back to the PR issue (see below).
Using IntelliJ IDEA
This is based on IDEA version 2019.3.
Code Style
The ./gradlew spotlessCheck task uses the eclipse formatting settings in eclipse-format.prefs to enforce a consistent format (we use the eclipse formatter because there's no support for running the IDEA formatter in CI).
Settings for IntelliJ that closely match this are in .editorconfig, to provider formatting while-you-type. In Settings > Editor > Code Style make sure Enable EditorConfig support is checked. These settings only closely match, though: continuation indentation behaviour differs.
To ensure ./gradlew spotlessCheck passes without having to run ./gradlew spotlessApply, you can use the following plugins and settings to make IntelliJ correctly format your code when you save a file:
-
Install the Eclipse Code Formatter plugin
-
Install the Save Actions plugin
-
Restart the IDE
-
Open
Settings, navigate toOther Settings > Eclipse Code Formatter, and apply the following settings:
...i.e.:
Use the Eclipse Code Formatteris on;Enable Javais on- The
eclipse-format.prefsin your checked-out fallout repo is selected as theEclipse Java Formatter config file.
-
Navigate to
Other Settings > Save Actions, and apply the following settings:
...i.e.:
Activate save actions on saveis on;Reformat only changed codeis on.
Importing as a project or module
-
Import
build.gradleas a gradle project or module. You can safely ignore any messages aboutDuplicate content roots detected. -
Open
Project Structure..., and make sure a Java 17 Project JDK is set. -
Open
Settings, navigate toBuild, Execution, Deployment > Compiler > Annotation Processors, and make sure theEnable annotation processingcheckbox is checked:
-
Then. navigate to
Build, Execution, Deployment > Build Tools > Gradleand make sure that the settings are as follows:
...i.e.:
Generate *.iml files for modules imported from Gradleis off;Build and run usingandRun tests usingare both set toGradle;Use Gradle fromis set to'gradle-wrapper.properties' file;- and
Gradle JVMisUse Project JDK.
-
In the toolbar drop-down at the top of the main window, select
Edit Configurations..., go toTemplates > Gradle, and set theEnvironment Variablesas follows (click[=]button):JAVA_HOME: the installation of the Java 17 JDKJAVA8_HOME: the installation of the Java 8 JDK
In order to run the full suite of unit tests, these must also be set:
UNIT_TEST_GOOGLE_SERVICE_ACCOUNT_JSON_FILE: (path to your Google Cloud service account json key file)
-
To run the fallout server, open the Gradle panel, navigate to
fallout > Tasks > applicationand double-clickrunServer.
Known issues
Until KTIJ-19483 is fixed, IDEA will show incorrect syntax errors in the build-logic code. A (not very satisfactory) workaround is to edit each build-logic sub-project in its own IDEA project.