`.
+
+E.g. for the previous example, you could use `@bullseye//perl/amd64:data`.
+
+### Lockfiles
+
+As mentioned, the macro can be used without a lock because the lock will be
+generated internally on-demand. However, this comes with the cost of
+performing a new package resolution on repository cache misses.
+
+The lockfile can be generated by running `bazel run @bullseye//:lock`. This
+will generate a `.lock.json` file of the same name and in the same path as
+the YAML `manifest` file.
+
+If you explicitly want to run without a lock and avoid the warning messages
+set the `nolock` argument to `True`.
+
+### Best Practice: use snapshot archive URLs
+
+While we strongly encourage users to check in the generated lockfile, it's
+not always possible because Debian repositories are rolling by default.
+Therefore, a lockfile generated today might not work later if the upstream
+repository removes or publishes a new version of a package.
+
+To avoid this problems and increase the reproducibility it's recommended to
+avoid using normal Debian mirrors and use snapshot archives instead.
+
+Snapshot archives provide a way to access Debian package mirrors at a point
+in time. Basically, it's a "wayback machine" that allows access to (almost)
+all past and current packages based on dates and version numbers.
+
+Debian has had snapshot archives for [10+
+years](https://lists.debian.org/debian-announce/2010/msg00002.html). Ubuntu
+began providing a similar service recently and has packages available since
+March 1st 2023.
+
+To use this services simply use a snapshot URL in the manifest. Here's two
+examples showing how to do this for Debian and Ubuntu:
+ * [/examples/debian_snapshot](/examples/debian_snapshot)
+ * [/examples/ubuntu_snapshot](/examples/ubuntu_snapshot)
+
+For more infomation, please check https://snapshot.debian.org and/or
+https://snapshot.ubuntu.com.
+"""
+
+install = tag_class(
+ attrs = {
+ "name": attr.string(
+ doc = "Name of the generated repository",
+ mandatory = True,
+ ),
+ "manifest": attr.label(
+ doc = "The file used to generate the lock file",
+ mandatory = True,
+ ),
+ "lock": attr.label(
+ doc = "The lock file to use for the index.",
+ ),
+ "nolock": attr.bool(
+ doc = "If you explicitly want to run without a lock, set it " +
+ "to `True` to avoid the DEBUG messages.",
+ default = False,
+ ),
+ "package_template": attr.label(
+ doc = "(EXPERIMENTAL!) a template file for generated BUILD " +
+ "files.",
+ ),
+ "resolve_transitive": attr.bool(
+ doc = "Whether dependencies of dependencies should be " +
+ "resolved and added to the lockfile.",
+ default = True,
+ ),
+ },
+ doc = _install_doc,
+)
apt = module_extension(
implementation = _distroless_extension,
diff --git a/apt/private/BUILD.bazel b/apt/private/BUILD.bazel
index 0b35ece..12a098d 100644
--- a/apt/private/BUILD.bazel
+++ b/apt/private/BUILD.bazel
@@ -27,6 +27,7 @@ bzl_library(
visibility = ["//apt:__subpackages__"],
deps = [
":lockfile",
+ "@bazel_tools//tools/build_defs/repo:cache.bzl",
"@bazel_tools//tools/build_defs/repo:http.bzl",
"@bazel_tools//tools/build_defs/repo:utils.bzl",
],
diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel
index 5b6848b..36b15eb 100644
--- a/docs/BUILD.bazel
+++ b/docs/BUILD.bazel
@@ -13,6 +13,12 @@ stardoc_with_diff_test(
stardoc_with_diff_test(
name = "apt",
+ bzl_library_target = "//apt:extensions",
+ target_compatible_with = COMPATIBLE,
+)
+
+stardoc_with_diff_test(
+ name = "apt_macro",
bzl_library_target = "//apt:apt",
target_compatible_with = COMPATIBLE,
)
diff --git a/docs/apt.md b/docs/apt.md
index 9d0788a..8a139f5 100644
--- a/docs/apt.md
+++ b/docs/apt.md
@@ -1,44 +1,30 @@
-apt-get
+apt extensions
-
+
-## apt.install
+## apt
-load("@rules_distroless//apt:apt.bzl", "apt")
-
-apt.install(name, manifest, lock, nolock, package_template, resolve_transitive)
+apt = use_extension("@rules_distroless//apt:extensions.bzl", "apt")
+apt.install(name, lock, manifest, nolock, package_template, resolve_transitive)
-A convience repository macro for apt rules.
-This documentation provides an overview of the convenience repository macro around `package_index` and `resolve` repository rules.
+**TAG CLASSES**
-### WORKSPACE Example
+
-```starlark
-load("@rules_distroless//apt:index.bzl", "deb_index")
+### install
-deb_index(
- name = "bullseye",
- # For the initial setup, the lockfile attribute can be omitted and
- # generated by running
- # bazel run @bullseye//:lock
- # This will generate the lock.json file next to the manifest file by
- # replacing `.yaml` with `.lock.json`.
- # If you explicitly want to run without a lock, set nolock to True to
- # avoid the DEBUG messages
- lock = "//examples/apt:bullseye.lock.json",
- manifest = "//examples/apt:bullseye.yaml",
-)
+Module extension to create Debian repositories.
-load("@bullseye//:packages.bzl", "bullseye_packages")
-bullseye_packages()
-```
+Create Debian repositories with packages "installed" in them and available
+to use in Bazel.
-### BZLMOD Example
+
+Here's an example how to create a Debian repo:
```starlark
apt = use_extension("@rules_distroless//apt:extensions.bzl", "apt")
@@ -50,45 +36,82 @@ apt.install(
use_repo(apt, "bullseye")
```
-### Macro Expansion
+Note that, for the initial setup (or if we want to run without a lock) the
+lockfile attribute can be omitted. All you need is a YAML
+[manifest](/examples/debian_snapshot/bullseye.yaml):
+```yaml
+version: 1
+
+sources:
+ - channel: bullseye main
+ url: https://snapshot-cloudflare.debian.org/archive/debian/20240210T223313Z
+
+archs:
+ - amd64
+
+packages:
+ - perl
+```
+
+`apt.install` will parse the manifest and will fetch and install the packages
+for the given architectures in the Bazel repo `@`.
-This macro will expand to two repositories: `#name` and `#name#_resolve`.
+Each `/` has two targets that match the usual structure of a
+Debian package: `data` and `control`.
-### Typical Workflow
+You can use the package like so: `@///:`.
-A typical workflow for `deb_index` involves the generation of a lockfile (`deb_resolve`) and the consumption of the lockfile by `deb_package_index` for generating a DAG.
+E.g. for the previous example, you could use `@bullseye//perl/amd64:data`.
-#### Lockfile Generation
+### Lockfiles
-The lockfile generation can be on-demand by omitting the `lock` attribute. However, this comes with the cost of performing a new package resolution on repository cache misses.
+As mentioned, the macro can be used without a lock because the lock will be
+generated internally on-demand. However, this comes with the cost of
+performing a new package resolution on repository cache misses.
-While we strongly encourage users to check in the generated lockfile, it's not always possible because Debian repositories are rolling by default. Therefore, a lockfile generated today might not work later if the upstream repository removes or publishes a new version of a package.
+The lockfile can be generated by running `bazel run @bullseye//:lock`. This
+will generate a `.lock.json` file of the same name and in the same path as
+the YAML `manifest` file.
-If you explicitly want to run without a lock, set the `nolock` attribute to True to avoid the DEBUG messages.
+If you explicitly want to run without a lock and avoid the warning messages
+set the `nolock` argument to `True`.
-#### Snapshot repositories
+### Best Practice: use snapshot archive URLs
-##### Debian
-Users can still use a `snapshot` repository and check in the generated lockfiles. This is possible because `snapshot.debian.org` is an immutable point-in-time snapshot of the upstream repositories, meaning packages never get deleted or updated in a specific snapshot.
+While we strongly encourage users to check in the generated lockfile, it's
+not always possible because Debian repositories are rolling by default.
+Therefore, a lockfile generated today might not work later if the upstream
+repository removes or publishes a new version of a package.
-An example of this can be found at [/examples/debian_snapshot](/examples/debian_snapshot).
+To avoid this problems and increase the reproducibility it's recommended to
+avoid using normal Debian mirrors and use snapshot archives instead.
-##### Ubuntu
-Ubuntu also has a similar point-in-time snapshot service hosted at `snapshot.ubuntu.com`, which can be used similarly.
+Snapshot archives provide a way to access Debian package mirrors at a point
+in time. Basically, it's a "wayback machine" that allows access to (almost)
+all past and current packages based on dates and version numbers.
-An example of this can be found at [/examples/ubuntu_snapshot](/examples/ubuntu_snapshot).
+Debian has had snapshot archives for [10+
+years](https://lists.debian.org/debian-announce/2010/msg00002.html). Ubuntu
+began providing a similar service recently and has packages available since
+March 1st 2023.
+To use this services simply use a snapshot URL in the manifest. Here's two
+examples showing how to do this for Debian and Ubuntu:
+ * [/examples/debian_snapshot](/examples/debian_snapshot)
+ * [/examples/ubuntu_snapshot](/examples/ubuntu_snapshot)
-**PARAMETERS**
+For more infomation, please check https://snapshot.debian.org and/or
+https://snapshot.ubuntu.com.
+**Attributes**
-| Name | Description | Default Value |
-| :------------- | :------------- | :------------- |
-| name | name of the repository | none |
-| manifest | label to a `manifest.yaml` | none |
-| lock | label to a `lock.json` | `None` |
-| nolock | bool, set to True if you explicitly want to run without a lock and avoid the DEBUG messages. | `False` |
-| package_template | (EXPERIMENTAL!) a template file for generated BUILD files. Available template replacement keys are: `{target_name}`, `{deps}`, `{urls}`, `{name}`, `{arch}`, `{sha256}`, `{repo_name}` | `None` |
-| resolve_transitive | whether dependencies of dependencies should be resolved and added to the lockfile. | `True` |
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| name | Name of the generated repository | Name | required | |
+| lock | The lock file to use for the index. | Label | optional | `None` |
+| manifest | The file used to generate the lock file | Label | required | |
+| nolock | If you explicitly want to run without a lock, set it to `True` to avoid the DEBUG messages. | Boolean | optional | `False` |
+| package_template | (EXPERIMENTAL!) a template file for generated BUILD files. | Label | optional | `None` |
+| resolve_transitive | Whether dependencies of dependencies should be resolved and added to the lockfile. | Boolean | optional | `True` |
diff --git a/docs/apt_macro.md b/docs/apt_macro.md
new file mode 100644
index 0000000..4576efc
--- /dev/null
+++ b/docs/apt_macro.md
@@ -0,0 +1,122 @@
+
+
+`apt.install` macro
+
+This documentation provides an overview of the convenience `apt.install`
+repository macro to create Debian repositories with packages "installed" in
+them and available to use in Bazel.
+
+
+
+## apt.install
+
+
+load("@rules_distroless//apt:apt.bzl", "apt")
+
+apt.install(name, manifest, lock, nolock, package_template, resolve_transitive)
+
+
+Repository macro to create Debian repositories.
+
+> [!WARNING]
+> THIS IS A LEGACY MACRO. Use it only if you are still using `WORKSPACE`.
+> Otherwise please use the [`apt` module extension](apt.md).
+
+Here's an example to create a Debian repo with `apt.install`:
+
+```starlark
+# WORKSPACE
+
+load("@rules_distroless//apt:apt.bzl", "apt")
+
+apt.install(
+ name = "bullseye",
+ # lock = "//examples/apt:bullseye.lock.json",
+ manifest = "//examples/apt:bullseye.yaml",
+)
+
+load("@bullseye//:packages.bzl", "bullseye_packages")
+bullseye_packages()
+```
+
+Note that, for the initial setup (or if we want to run without a lock) the
+lockfile attribute can be omitted. All you need is a YAML
+[manifest](/examples/debian_snapshot/bullseye.yaml):
+```yaml
+version: 1
+
+sources:
+ - channel: bullseye main
+ url: https://snapshot-cloudflare.debian.org/archive/debian/20240210T223313Z
+
+archs:
+ - amd64
+
+packages:
+ - perl
+```
+
+`apt.install` will parse the manifest and will fetch and install the
+packages for the given architectures in the Bazel repo `@`.
+
+Each `/` has two targets that match the usual structure of a
+Debian package: `data` and `control`.
+
+You can use the package like so: `@///:`.
+
+E.g. for the previous example, you could use `@bullseye//perl/amd64:data`.
+
+### Lockfiles
+
+As mentioned, the macro can be used without a lock because the lock will be
+generated internally on-demand. However, this comes with the cost of
+performing a new package resolution on repository cache misses.
+
+The lockfile can be generated by running `bazel run @bullseye//:lock`. This
+will generate a `.lock.json` file of the same name and in the same path as
+the YAML `manifest` file.
+
+If you explicitly want to run without a lock and avoid the warning messages
+set the `nolock` argument to `True`.
+
+### Best Practice: use snapshot archive URLs
+
+While we strongly encourage users to check in the generated lockfile, it's
+not always possible because Debian repositories are rolling by default.
+Therefore, a lockfile generated today might not work later if the upstream
+repository removes or publishes a new version of a package.
+
+To avoid this problems and increase the reproducibility it's recommended to
+avoid using normal Debian mirrors and use snapshot archives instead.
+
+Snapshot archives provide a way to access Debian package mirrors at a point
+in time. Basically, it's a "wayback machine" that allows access to (almost)
+all past and current packages based on dates and version numbers.
+
+Debian has had snapshot archives for [10+
+years](https://lists.debian.org/debian-announce/2010/msg00002.html). Ubuntu
+began providing a similar service recently and has packages available since
+March 1st 2023.
+
+To use this services simply use a snapshot URL in the manifest. Here's two
+examples showing how to do this for Debian and Ubuntu:
+ * [/examples/debian_snapshot](/examples/debian_snapshot)
+ * [/examples/ubuntu_snapshot](/examples/ubuntu_snapshot)
+
+For more infomation, please check https://snapshot.debian.org and/or
+https://snapshot.ubuntu.com.
+
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| name | name of the repository | none |
+| manifest | label to a `manifest.yaml` | none |
+| lock | label to a `lock.json` | `None` |
+| nolock | bool, set to True if you explicitly want to run without a lock and avoid the DEBUG messages. | `False` |
+| package_template | (EXPERIMENTAL!) a template file for generated BUILD files. Available template replacement keys are: `{target_name}`, `{deps}`, `{urls}`, `{name}`, `{arch}`, `{sha256}`, `{repo_name}` | `None` |
+| resolve_transitive | whether dependencies of dependencies should be resolved and added to the lockfile. | `True` |
+
+