Testing and command list

Goat groups the most common development operations into .goat scripts located in the herd/ directory.

Instead of manually running successive Docker, generator, migration, test, or frontend tool commands, you can describe the entire process as a single repeatable workflow and run it with one command.

The scripts are executed using Goat's isolation layer. This allows the dependencies and tools required by the project to run in containers, without needing to install them directly on the host system.

This approach provides several benefits:

  • standardizes how the project is run across different operating systems,
  • reduces dependence on the developer's local machine configuration,
  • makes it possible to control versions of Go, Node.js, browsers, and other tools,
  • limits the scope of changes made by scripts to resources shared by the project,
  • simplifies running the same processes locally and in CI.

Daily work

The most commonly used commands:

PurposeCommand
Start the development environmentgoat run:script --path=herd/dev.goat
Regenerate the applicationgoat re
Run database migrationsgoat run:script --path=herd/db/migrate.goat
Clear the local databasegoat run:script --path=herd/db/clean.goat
Run the full test suitegoat run:script --path=herd/test.goat
Synchronize translationsgoat run:script --path=herd/translate.goat

goat run:script

The run:script command runs the specified .goat file:

goat run:script --path=herd/dev.goat

The script file can describe an entire process consisting of multiple steps, for example:

  • starting containers,
  • preparing dependencies,
  • generating code,
  • running migrations,
  • running tests,
  • building the frontend,
  • starting the application.

This keeps the development environment logic as part of the project, rather than spreading it across documentation, local scripts, and the configurations of individual developers' machines.

goat re

The command:

goat re

reruns the application generation process based on the current model and project configuration.

You will most commonly use it after changes to:

  • the domain model,
  • entity definitions,
  • relationships,
  • generator configuration,
  • generated code templates.

The generator should make changes in a controlled manner so that the generated application can continue to be developed manually.

After regeneration, it is worth checking the Git diff before committing it.

Testing

You can run the full test suite with:

goat run:script --path=herd/test.goat

herd/test.goat defines the complete application verification process.

Before running the actual tests, the script recreates the generated part of the project. This ensures that the code corresponding to the current application model is tested, rather than an arbitrary local state of generated files.

The following are then run, among others:

  • Go backend tests,
  • frontend application build,
  • frontend tests,
  • Playwright-based E2E tests.

Where possible, independent stages may run in parallel, reducing the duration of the entire process.

Repeatable test environment

Tests use containers to reduce differences between developers' environments and CI.

This applies in particular to components such as:

  • Go,
  • Node.js,
  • npm,
  • browsers used by Playwright,
  • PostgreSQL,
  • additional tools required when building the application.

As a result, test outcomes should not depend on which version of Node.js or Go a developer currently has installed on their computer.

This is particularly important for E2E tests, which are often sensitive to browser versions and system dependencies.

Isolation during testing and building

Running tools in containers also serves a security purpose.

Operations such as:

npm install
npm test
npm run build

do not need to be performed directly on the host.

Code executed by dependencies runs within a controlled environment and is granted access only to resources exposed by Goat and the project configuration.

This helps reduce, among other things, risks associated with dependency installation scripts such as preinstall, install, or postinstall.

At the same time, isolation does not replace dependency control. It is still worth:

  • reviewing library updates,
  • using a lockfile,
  • controlling dependency sources,
  • checking changes before committing them.

Reviewing changes after generation

After running:

goat re

or the full test process, it is worth reviewing the changes:

git status
git diff

This makes it possible to see exactly which parts of the application were modified by the generator.

This is particularly useful when changing the domain model. Rather than treating regeneration as an “overwrite the entire application” operation, Goat lets you work with generated changes similarly to manually introduced changes.

You can commit only those files that should actually be included in a given commit.

Debugging scripts

If one of the workflows does not complete successfully, first run the corresponding script directly.

For example, migration issues can be reproduced using:

goat run:script --path=herd/db/migrate.goat

and test issues:

goat run:script --path=herd/test.goat

Splitting processes into smaller .goat scripts makes it easier to determine whether the issue concerns:

  • generation,
  • the database,
  • the backend,
  • the frontend,
  • E2E tests,
  • environment configuration.

Help for application commands

The generated application also includes its own CLI.

After building it, you can display documentation for individual commands using the --help flag.

For example:

myapp crud:doc:persist --help
myapp db:migrate --help
myapp serve --help

It is worth using --help instead of relying solely on examples from the documentation, as it shows the parameters available in the currently used version of the application.

Example: crud:doc:persist

The command:

myapp crud:doc:persist --help

displays options for creating or updating a document.

Available parameters include, among others:

  • --lang,
  • --slug,
  • --title,
  • --description,
  • --body-markdown,
  • --body-markdown-file.

For larger content, it is more convenient to provide a file:

myapp crud:doc:persist \
  --lang=pl \
  --slug=testowanie \
  --title="Testowanie" \
  --body-markdown-file=./doc/testowanie.md

This allows documentation content to be stored in the repository and synchronized with the application using the CLI.

Releases

The process for preparing a new release is described in the file:

RELEASING.md

It contains a procedure covering, among other things:

  • selecting and setting the new version,
  • preparing the required keys,
  • building artifacts,
  • running tests,
  • verifying packages,
  • publishing the release.

Do not skip the full test suite before publishing.

Before starting the release process, it is also worth checking:

git status

and ensuring that the repository does not contain any accidental local changes.

A release should only be prepared when:

  • the generator works correctly for the current model,
  • backend tests pass,
  • the frontend builds correctly,
  • E2E tests pass,
  • the target environment configuration has been verified,
  • all changes intended for the release are present in the repository.

Typical workflow

In day-to-day work, the following cycle is usually sufficient:

# modify the application model
vim herd/_model.goat

# generate the resulting changes
goat re

# check the generated code
git diff

# run the tests
goat run:script --path=herd/test.goat

# check the final scope of changes
git status

This way of working helps maintain a clear separation of responsibilities:

the model describes the intent, the generator produces repeatable code, tests verify the result, and Git remains the ultimate source of information about what has actually changed in the project.