Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"permissions": {
"allow": [
"Bash(gh issue *)",
"Bash(buildifier)",
"Bash(echo \"exit: $?\")"
]
}
}
161 changes: 161 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# rules_pkg — Claude Code guide

rules_pkg is a set of Bazel rules for building distribution packages (tar, zip, deb, rpm, …).
The core abstraction is a set of package-format-agnostic mapping rules (`pkg_files`,
`pkg_filegroup`, `pkg_mkdirs`, `pkg_mklink`) that describe *what* goes where in a package;
format-specific rules (`pkg_tar`, `pkg_zip`, `pkg_deb`, `pkg_rpm`) consume those descriptions.

## Repository layout

```
pkg/ Runtime rules and providers (shipped in the distribution)
mappings.bzl pkg_files, pkg_filegroup, pkg_mkdirs, pkg_mklink
providers.bzl PackageVariablesInfo and other providers
private/ Internal implementation helpers (not public API)
util.bzl substitute_package_variables, setup_output_files, …
deb/ pkg_deb implementation
tar/ pkg_tar implementation
zip/ pkg_zip implementation
tests/ All tests (not shipped)
mappings/ Analysis tests for pkg_files / pkg_filegroup
tar/ Tests for pkg_tar
deb/ Tests for pkg_deb
rpm/ Tests for pkg_rpm
zip/ Tests for pkg_zip
examples/ Runnable examples (tested in CI)
docs/ Generated reference docs (do not edit by hand)
distro/ Rules to build the distribution tarball
```

Top-level `.bzl` shims (`mappings.bzl`, `pkg.bzl`, etc.) are backward-compatibility
re-exports of the files inside `pkg/`.

## Code style

### Starlark / BUILD files — always run buildifier after editing

After editing any `.bzl` or `BUILD` file, run:

```
buildifier --lint=fix <FILE>
```

buildifier enforces load ordering, argument sorting, and other canonical style.
It will reorder loads alphabetically; let it.

### Starlark conventions

- All public rule attributes must have a `doc =` string.
- Use `substitute_package_variables(ctx, value)` (from `//pkg/private:util.bzl`)
to expand `$(VAR)` make-variable syntax in string attributes.
The rule must also declare a `package_variables` attribute typed
`attr.label(providers = [PackageVariablesInfo])`.
- Prefer solutions that work for all package formats (via `pkg_files`/`pkg_filegroup`)
over format-specific additions.
- Actions must not write quoted strings directly to command lines — write paths to
an intermediate file instead.

### Python

- Python 3 only; no Python 2 support.
- Always import with full paths from the workspace root.
- No new third-party package dependencies — standard library only.

### General

- No files should have trailing whitespace.
- Try to keep lines under 100 characters long.

## Testing

**All features and bug fixes must have tests.**

### Mappings (pkg_files / pkg_filegroup)

Tests live in `tests/mappings/mappings_test.bzl` and are registered via the
`mappings_analysis_tests()` macro called from `tests/mappings/BUILD`.

- Use `pkg_files_contents_test` (defined in `mappings_test.bzl`) to assert
expected destination paths from a `pkg_files` target.
- Use `pkg_filegroup_contents_test` to compare a `pkg_filegroup` output against
reference `pkg_files` / `pkg_mkdirs` / `pkg_mklink` targets.
- Use `generic_negative_test` for targets that are expected to fail analysis.
- Add new test names to the `pkg_files_analysis_tests` test suite list at the
bottom of `mappings_analysis_tests()`.

Run them with:

```
bazel test //tests/mappings/...
```

### package_variables / make-variable substitution

The sample naming rule used across tests is `my_package_naming` in
`tests/my_package_name.bzl`. Load it as:

```python
load("//tests:my_package_name.bzl", "my_package_naming")
```

Create an instance, then wire it to the `package_variables` attribute of
the rule under test. Example:

```python
my_package_naming(name = "my_vars", label = "linux_x86_64", tags = ["manual"])

pkg_files(
name = "my_files",
srcs = [...],
prefix = "usr/lib/$(label)",
package_variables = ":my_vars",
tags = ["manual"],
)
```

### Format-specific tests

```
bazel test //tests/tar/...
bazel test //tests/deb/...
bazel test //tests/zip/...
bazel test //tests/rpm/... # may require rpm toolchain
```

### Running everything

```
bazel test //tests/...
```

## Regenerating docs

After any feature change, regenerate the reference docs before committing:

```
bazel build //doc_build:reference
cp bazel-bin/doc_build/reference.md docs/latest.md
```

Do **not** `git commit` yet — that is a separate step the user will handle.

## Common patterns

### Adding package_variables support to an attribute

1. Import `PackageVariablesInfo` from `//pkg:providers.bzl` and
`substitute_package_variables` from `//pkg/private:util.bzl`.
2. Add to the rule attrs:
```python
"package_variables": attr.label(
doc = """See [Common Attributes](#package_variables)""",
providers = [PackageVariablesInfo],
),
```
3. In the implementation, call substitution at the top before using the value:
```python
prefix = substitute_package_variables(ctx, ctx.attr.prefix)
```
4. Use the substituted local variable everywhere instead of `ctx.attr.prefix`.
5. Run `buildifier --lint=fix` on the modified file.
6. Add analysis tests in the appropriate test file.
Loading
Loading