grept
stands for GoREPositorylinTer.
grept
is a powerful, extensible linting tool for repositories. Inspired by RepoLinter, grept
is designed to ensure that your repositories follow certain predefined standards. It parses and evaluates configuration files, generates plans based on the specified configuration, and applies the plans. This makes it an excellent tool for maintaining consistency and quality in your codebase.
grept
is written in Golang, using cobra for command-line interface and afero for file system abstraction. This makes it both highly extensible and testable.
You can install grept
directly using the go install
command:
go install github.com/Azure/grept@latest
Please make sure you have Go installed and your GOPATH
properly set up.
grept
supports two commands: plan
and apply
.
The plan
command generates a plan based on the specified configuration.
grept plan [path-to-config-folder]
Replace [path-to-config-folder]
with your configuration files folder's path. The plan
command will parse all files with suffix *.grept.hcl
and generate a plan. If all rule checks are successful, it will print "All rule checks successful, nothing to do." Otherwise, it will print the plan.
Omitting [path-to-config-folder]
will use the current folder instead.
The apply
command applies the plan generated by the plan
command.
grept apply [path-to-config-folder]
Replace [path-to-config-folder]
with your configuration files folder's path. The apply
command will apply the fixes to the issues found by the plan
command. If all fixes are applied successfully, it will print "Plan applied successfully."
Omitting [path-to-config-folder]
will use the current folder instead.
You can use the -a
or --auto
flag to apply fixes without confirmation.
grept apply -a [path-to-config-folder]
The config folder path support multiple different types:
- Local paths
- Terraform Registry
- GitHub
- Bitbucket
- Generic Git, Mercurial repositories
- HTTP URLs
- S3 buckets
- GCS buckets
An example:
grept apply git::https://github.com/lonegunmanb/grept-example-config.git//mit-example
You can check Terraform Module sources document for more details.
The following example config file would ensure that your repository contains a MIT license file:
data http mit_license {
url = "https://raw.githubusercontent.com/Azure/terraform-verified-module/main/LICENSE"
}
rule file_hash license {
glob = "LICENSE"
hash = sha1(data.http.mit_license.response_body)
}
fix local_file license {
rule_ids = [rule.file_hash.license.id]
paths = [rule.file_hash.glob]
content = data.http.mit_license.response_body
}
All built-in functions provided by HashiCorp Packer are available.
All toxxx
functions provided by Terraform 1.5.7
are supported:
tostring
tonumber
tobool
toset
tolist
tomap
We've provided the following new functions:
env
: To read environment variable, likeenv("GITHUB_REPOSITORY")
.compliment
: Return the compliment of multiple lists.yaml2json
: Convert yaml to corresponding json string.
It seems like go-cty-yaml
has a bug, so please do not use yamldecode
function to parse and check Github action yaml files. I added this yaml2json
function so you can convert yaml string to json first, then use jsondecode
function to unmarshal it and check whether the github action file meets your requirement.
You can find detailed explanations about different components of the grept
tool.
The documents are organized by categories: rule
blocks, data
blocks, and fix
blocks.
Rule blocks define the rules that should be enforced in the repository.
Data blocks define the data that should be collected from the repository.
git_ignore
github_repository_collaborators
github_repository_environments
github_repository_teams
http
Fix blocks define the actions that should be taken when a rule fails.
copy_file
git_ignore
github_repository_collaborators
github_repository_environments
github_team
github_team_members
github_team_repository
local_file
local_shell
rename_file
rm_local_file
yaml_transform
For each block type, you can find detailed information about the block's attributes, exported attributes, and usage examples.
You can define and use locals
block in grept
just like Terraform.
You can use for_each
like Terraform. for_each
is a meta-argument, it can be used with:
data
rule
fix
The for_each
meta-argument accepts a map or a set of strings, and creates an instance for each item in that map or set. Each instance has a distinct block associated with it, and each is separately planed and applied.
locals {
items = toset(["item1", "item2", "item3"])
}
data "http" echo {
for_each = local.items
url = "http://foo"
request_body = jsonencode({
query = each.value
})
}
rule "must_be_true" sample {
for_each = local.items
condition = each.value != data.http.echo[each.value]response_body
}
fix "local_file" hello_world{
for_each = local.items
rule_ids = [rule.must_be_true.sample[each.value].id]
paths = [each.value]
content = each.value
}
The precondition
block is used to specify a condition that must be met before a block is evaluated. This is useful for adding checks that prevent the rule from running when certain conditions are not met.
Here is an example of a precondition
block that checks if the GITHUB_TOKEN
environment variable exists:
rule "must_be_true" "check_env" {
precondition {
condition = env("GITHUB_TOKEN") != ""
error_message = "GITHUB_TOKEN environment variable must be set"
}
condition = true
}
Contributions to grept
are welcome! Please submit a pull request or issue on the grept GitHub page.
grept
is released under the MIT license. For more information, see LICENSE.