Skip to content

Commit

Permalink
Docs: Document fixing issues, project roots, and new features
Browse files Browse the repository at this point in the history
This is a follow-up PR to #1035, documenting the new capabilities
of Regal added there

Signed-off-by: Anders Eknert <anders@styra.com>
  • Loading branch information
anderseknert authored and charlieegan3 committed Sep 4, 2024
1 parent ccb66fc commit 2969350
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 19 deletions.
80 changes: 71 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
[![Build Status](https://github.com/styrainc/regal/workflows/Build/badge.svg?branch=main)](https://github.com/styrainc/regal/actions)
![OPA v0.68.0](https://openpolicyagent.org/badge/v0.68.0)

Regal is a linter and language server for [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), helping
you write better policies and have fun while doing it!
Regal is a linter and language server for [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), making
your Rego magnificent, and you the ruler of rules!

With its extensive set of linter rules, documentation and editor integrations, Regal is the perfect companion for policy
development, whether you're an experienced Rego developer or just starting out.

<img
src="/docs/assets/regal-banner.png"
Expand All @@ -22,12 +25,7 @@ you write better policies and have fun while doing it!
- Identify common mistakes, bugs and inefficiencies in Rego policies, and suggest better approaches
- Provide advice on [best practices](https://github.com/StyraInc/rego-style-guide), coding style, and tooling
- Allow users, teams and organizations to enforce custom rules on their policy code

Regal rules are to as large extent as possible
[written in Rego](https://www.styra.com/blog/linting-rego-with-rego/) themselves,
using the JSON representation of the Rego abstract syntax tree (AST) as input, a
few additional custom built-in functions and some indexed data structures to help
with linting.
- Deliver an outstanding policy development experience by providing the best possible tools for that purpose

## What People Say About Regal

Expand Down Expand Up @@ -156,7 +154,28 @@ Documentation: https://docs.styra.com/regal/rules/style/prefer-snake-case
> will likely generate a lot of violations. You can do this by passing the `--disable-category style` flag to
> `regal lint`.
### Using Regal in your build pipeline!
### Using Regal in Your Editor

Linting from the command line is a great way to get started with Regal, and even for some experienced developers
the preferred way to work with the linter. However, not only is Regal a linter, but a full-fledged development
companion for Rego development!

Integrating Regal in your favorite editor means you'll get immediate feedback from the linter as you work on your
policies. More than that, it'll unlock a whole new set of features that leverage Regal's
[language server](#regal-language-server), like context-aware completion suggestions, informative tooltips on hover,
or go-to-definition.

- Get started with Regal for VS Code by installing Regal (per the instructions above) and the
[OPA VS Code extension](https://marketplace.visualstudio.com/items?itemName=tsandall.opa)
- Get started with Regal for Zed by installing the [zed-rego](https://github.com/StyraInc/zed-rego) extension
- Get started with Regal in Neovim using any of the available
[Regal plug-ins](https://docs.styra.com/regal/editor-support#neovim)

See the page on [Editor Support](https://docs.styra.com/regal/editor-support) to learn more about how to use Regal
in your editor of choice. To learn more about the features provided by the Regal language server, see the
[Language Server](https://docs.styra.com/regal/language-server) page.

### Using Regal in Your Build Pipeline

To ensure Regal's rules are enforced consistently in your project or organization,
we've made it easy to run Regal as part of your builds.
Expand Down Expand Up @@ -356,6 +375,12 @@ ignore:
files:
- file1.rego
- "*_tmp.rego"

project:
roots:
# declares the 'main' and 'lib/jwt' directories as project roots
- main
- lib/jwt
```
Regal will automatically search for a configuration file (`.regal/config.yaml`) in the current directory, and if not
Expand Down Expand Up @@ -509,6 +534,43 @@ for the `regal lint` command:

**Note:** all CLI flags override configuration provided in file.

## Project Roots

While many projects consider the project's root directory (in editors often referred to as **workspace**) their
"main" directory for policies, some projects may contain code from other languages, policy "subprojects", or multiple
[bundles](https://www.openpolicyagent.org/docs/latest/management-bundles/). While most of Regal's features works
independently of this — linting, for example, doesn't consider where in a workspace policies are located as long as
those locations aren't [ignored](#ignoring-files-globally) — some features, like automatically
[fixing](https://docs.styra.com/regal/fixing) violations, benefit from knowing when a project contains multiple roots.

To provide an example, consider the
[directory-package-mismatch](https://docs.styra.com/regal/rules/idiomatic/directory-package-mismatch) rule, which states
that a file declaring a `package` path like `policy.permissions.users` should also be located in a directory structure
that mirrors that package, i.e. `policy/permissions/users`. When a violation against this rule is reported, the
`regal fix` command, or its equivalent [Code Action](#regal-language-server) in editors, may when invoked remediate the
issue by moving the file to the correct location. But where should the `policy/permissions/users` directory *itself*
reside?

By default, the answer to that question would be the **project**, or **workspace** root. But if the file was found
in a subdirectory containing a **bundle**, the directory naturally belongs under that *bundle's root* instead. The
`roots` configuration option under the top-level `project` object allows you to tell Regal where these roots are,
and have features that depend on this information work as expected.

```yaml
project:
roots:
- bundle1
- bundle2
```

The configuration file is not the only way Regal may determine project roots. Other ways include:

- A directory containing a `.manifest` file will automatically be registered as a root
- A directory containing a `.regal` directory will be registered as a root (this is normally the project root)

If a feature that depends on project roots fails to identify any, it will either fail or fall back on the directory
in which the command was run.

## Capabilities

By default, Regal will lint your policies using the
Expand Down
Binary file added docs/assets/lsp/code_action_fix.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/lsp/code_action_show.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 89 additions & 10 deletions docs/fixing.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,105 @@
# Fixing Violations

For each violation Regal is able to detect, there is a documentation page
explaining the issue in detail and how to fix it. For example, here's the one for
the [`prefer-some-in-iteration`](/regal/rules/style/prefer-some-in-iteration) rule.
For each violation Regal is able to detect, there is a documentation page explaining the issue in detail and how to fix
it. For example, here's the one for the [`prefer-some-in-iteration`](/regal/rules/style/prefer-some-in-iteration) rule.

Some rules are automatically fixable, meaning that Regal can fix the violation
for you. To automatically fix all supported violations, run:
Some rules are **automatically** fixable, meaning that Regal can fix the violation for you. Note that while most fixes
will make minor changes to the code, some fixes make more significant modifications. As an example, the
[directory-package-mismatch](https://docs.styra.com/regal/rules/idiomatic/directory-package-mismatch) fix will
automatically move a file to its idiomatic location based on the package path declared in the file.

```shell
regal fix <path> [path [...]] [flags]
```
:::tip
Before you make any automated fixes, make sure to commit any other changes you may have done in your project! That way
you can easily revert the changes if anything goes wrong, and this allows you to review the diff before committing the
fixes.
:::

Currently, the following rules are automatically fixable:

- [opa-fmt](/regal/rules/style/opa-fmt)
- [use-rego-v1](/regal/rules/imports/use-rego-v1)
- [use-assignment-operator](/regal/rules/style/use-assignment-operator)
- [no-whitespace-comment](/regal/rules/style/no-whitespace-comment)
- [directory-package-mismatch](https://docs.styra.com/regal/rules/idiomatic/directory-package-mismatch)

So, how do you go on about automatically fixing reported violations?

## The `regal fix` Command

The first method is to use `regal fix` from the command line. This command can be seen as the remediating counterpart
to `regal lint`, and most configuration options are the same. For example, a linter rule configured to be ignored by
the linter will also be ignored by the fixer. Typing `regal fix --help` will show you the available options, as well
as all the supported "fixers" for your version of Regal. Lets's see what automatically fixing violations looks like!

**Example**: fixing all files in the `bundle` directory:

```shell
> regal fix bundle
3 fixes applied:
In project root: /Users/john/projects/authz/bundle

lib/roles.rego:
- use-rego-v1

policy.rego -> main/policy.rego:
- directory-package-mismatch
- no-whitespace-comment
```

In the example above, Regal made fixes corresponding to the linter rules `use-rego-v1`, `directory-package-mismatch`,
and `no-whitespace-comment` in `lib/roles.rego` and `policy.rego`. While the number of fixes applied was reported as 3,
the number of _violations_ fixed could of course have been higher, as e.g. the `no-whitespace-comment` rule might have
been violated in multiple places in `policy.rego`. Note also how one of the fixes (`directory-package-mismatch`)
involved **moving** `policy.rego` to `main/policy.rego`, as that rule requires the file to be in a directory structure
matching its package path (`package main`).

### Project Roots

All paths are relative to its closest **project root**, as reported in the second line of the output. Most policy
projects will likely only have one "root", which is the workspace directory itself. More complex projects may however
host multiple roots inside the workspace, and defining these roots — either by configuration, or by `.manifest` files —
will in some cases (like the previously mentioned `directory-package-mismatch` fix) help Regal better apply the correct
fixes. See the documentation on [project roots](https://docs.styra.com/regal#project-roots) for more information.

### Dry Run

Using the `--dry-run` flag is a great way to see what changes will be made without actually applying them. Following our
example from above, adding the `--dry-run` flag to `regal fix bundle` would have told us beforehand what changes we
should expect to see. Make it a habit to dry-run your fixes before applying them, and make sure you've commited any
other changes before running the fixer!

## Fixing Violations in Editors

In addition to the `regal fix` command, users integratiing Regal with their editors can fix violations directly as
they are reported in the file being edited. This is done by means of Code Actions, which commonly displays a lightbulb
icon next to where a violation occurs. Clicking on the lightbulb will show a list of available actions, which in Regal's
case maps directly to the available fix for the violation reported (if any).

Example of code action in VS Code, where available fixes can be listed either by clicking the lightbulb icon to the
right, or by clicking "Quick Fix..." in the tooltip window:

<img
src={require('./assets/lsp/code_action_show.png').default}
alt="Screenshot of code action displayed in VS Code"/>

Example of suggested Code Action for the
[use-assignment-operator](https://docs.styra.com/regal/rules/style/use-assignment-operator) rule. Click to fix!

<img
src={require('./assets/lsp/code_action_fix.png').default}
alt="Screenshot of code action fix suggestion displayed in VS Code"/>

### Limitations

Compared to `regal fix`, automatically fixing violations in editors has some limitations:

- Normally works on one file at a time, not entire directories
- No ability to dry-run a fix, but on the other hand, the editor's **Undo** feature will let you easily revert any
changes made.

:::tip
Need to fix individual violations? Checkout the editors Regal supports
[here](/regal/editor-support).
If you're curious about using Regal to fix problems directly in your editor, see the docs on editor support
[here](/regal/editor-support) to learn more!
:::

## Community
Expand Down
1 change: 1 addition & 0 deletions docs/language-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Regal currently provides quick fix code actions for the following linter rules:
- [use-rego-v1](https://docs.styra.com/regal/rules/imports/use-rego-v1)
- [use-assignment-operator](https://docs.styra.com/regal/rules/style/use-assignment-operator)
- [no-whitespace-comment](https://docs.styra.com/regal/rules/style/no-whitespace-comment)
- [directory-package-mismatch](https://docs.styra.com/regal/rules/idiomatic/directory-package-mismatch)

### Code lenses (Evaluation)

Expand Down

0 comments on commit 2969350

Please sign in to comment.