Commit Graph

2274 Commits

Author SHA1 Message Date
Lorenz Leutgeb a354686bbc chore: Remove `seed.radicle.xyz`
The team node is not really special, remove occurrences.
2025-06-18 14:45:54 +02:00
Jakob Kirsch e30e66e009
radicle: add .external_template(false) to all other libgit2 calls
This complements 9d4aa59a12.
2025-06-14 00:28:06 +02:00
Fintan Halpenny ab62dce683 radicle: refactor Canonical
Changes for the `Canonical` type:
- Reorder arguments so that `delegates` and `threshold` are grouped
  after `refname`
- Add `Canonical::is_empty` to detect when `Canonical` was constructed
  with no tips
- Consume `Canonical` when calling `Canonical::quorum` to indicate
  that it should be the final step
2025-06-12 13:35:47 +02:00
Fintan Halpenny b2bcd561cf radicle: store threshold in Canonical
The Canonical type is generally constructed with the threshold, needed
for the quorum computation, in scope. To make it easier to use and
encapsulate its functionality, it now holds the threshold as an
additional field.
2025-06-12 13:19:48 +02:00
Fintan Halpenny b614167bd9 meta: relax radicle-git dependencies
Relax the set of radicle-git depedencies to allow for patches. In
particular, the dependencies introduced some small improvements with
`0.*.1` updates.
2025-06-12 13:01:38 +02:00
Lars Wirzenius 6e9517a186 fix Debian package building after crates have moved into a sub-dir
Signed-off-by: Lars Wirzenius <liw@liw.fi>
2025-06-10 07:40:59 +03:00
Lorenz Leutgeb 5bc2dc677b repo: Move workspace crates into `crates` subdirectory
This keeps the top level of the repo cleaner, e.g.
<https://github.com/radicle-dev/heartwood> scrolls less and
<https://app.radicle.xyz/nodes/rosa.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/>
might show more files at the top level.

This way we also don't have to explicitly name all crates in
`Cargo.toml`.
2025-06-09 15:09:21 +02:00
Lorenz Leutgeb 6259a70327 cargo: Use `workspace.package` table
This removes redundancy from the manifest of many of our crates.

See: <https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table>
2025-06-09 14:25:31 +02:00
Lorenz Leutgeb eea6a9bc70 cargo: Clean up dependencies
All dependencies that are dependencies of multiple crates within the
workspace were pulled up to the root `Cargo.toml`. Dependencies that are
dependencies of just one crate within the workspace remain in the
`*/Cargo.toml` of that particular crate.

Generally, this helps us keep an overview of dependencies:
 - If multiple crates depend on a crate, we will see the reference to
   the workspce.
 - Otherwise, we will see a line that specifies the version.

It is up to the maintainers to recognize when a dependency becomes a
dependency of multiple crates in the workspace, at which point it should
be moved to the workspace.

The tool `cargo-autoinherit` can be used to automatically pull *ALL*
dependencies to the workspace. I used this, and in a separate, manual
step, filtered out those dependencies that are dependencies of a single
crate only, moving those back manually.

At the same time, I also unified depending on sibling crates in the
workspace. This is now also done via workspace dependencies.

See:
 - https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#inheriting-a-dependency-from-a-workspace
 - https://github.com/mainmatter/cargo-autoinherit
2025-06-09 13:58:52 +02:00
Lorenz Leutgeb d50df68b74 chore: Remove dependency `once_cell`
Rust 1.80 introduced `std::sync::LazyLock` which achieves the same, so
cut down on dependencies a bit.

See: <https://doc.rust-lang.org/1.80.0/std/sync/struct.LazyLock.html>
2025-06-09 12:06:30 +02:00
Lorenz Leutgeb 3bc0db68f4 doc: Add `CHANGELOG.md`
Inspired by other projects, such as Jujutusu, add a `CHANGELOG.md` file
to be updated alongside the actual changes in the heartwood repository.

The file is pre-filled with some release hightlights of earlier releases
from the Radicle home page. The format for the upcoming release is
prepared with the same structure that Jujutsu uses, which is based on
the suggestions at <https://keepachangelog.com>.

See also: https://radicle.zulipchat.com/#narrow/channel/369277-heartwood/topic/Changelog.20in.20tree/with/522524869
2025-06-05 10:59:36 +02:00
Lorenz Leutgeb 0fd8c8be4d github: Add README.md
This file will be rendered if the repository is accessed via the GitHub
website. It contains the most imporant information from `/README.md`
and some additional information regarding the status of the repository
on GitHub.

Thanks for the pointer, Yorgos!

See also:
 - https://radicle.zulipchat.com/#narrow/channel/369277-heartwood/topic/github.20repo/with/522296878
 - https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes

Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
2025-06-05 09:26:26 +02:00
Lorenz Leutgeb bac719da21 bootstrap: Migrate radicle.garden → radicle.xyz 2025-06-04 17:13:02 +02:00
Jakob Kirsch 9d4aa59a12 radicle: add .external_template(false) to libgit2 call
Without this, rad clone fails with:
Error: checkout: git: failed to initialize repository with template 'hooks/README.sample': Permission denied; class=Os (2)
2025-06-04 12:15:59 +02:00
Sebastian Martinez a8ab718b98 chore(debian/changelog): update package version to match upstream 2025-06-03 17:55:02 +02:00
Sebastian Martinez 7380e2118b chore(debian/control): add sebastinez to Uploaders 2025-06-03 17:54:55 +02:00
Léon Zach eceb7f29c8 cob: Simplify the ChangeGraph implementation
Signed-off-by: Léon Zach <leon.zach@posteo.de>
2025-06-03 16:23:32 +02:00
Lorenz Leutgeb 4cd0782f2e radicle-schemars: Add crate for utility binary
Extracting JSON Schemas from the Radicle crate can be done via
`radicle-cli` for `radicle::profile::Config` by executing:

    rad config schema

However, for other JSON Schema metadata, this is not possible.

To allow other tools to extract JSON schemas as part of their build
process, introduce a new crate that only depends on `radicle`,
`schemars`, and `serde`, with a tiny binary that will reproduce various
schemas.
2025-06-03 15:10:30 +02:00
Lorenz Leutgeb fcd1acd1dd radicle/schemars: Annotate Commands and results
JSON Schema extraction via `schemars` is provided for configurations.
There are other interfaces that use JSON for (de-)serialization, such as
the communication with `radicle-node` via the control socket.

To ease implementation of tools that want to communicate via the control
socket, we add the respective `schemars` annotations.
2025-06-03 15:10:30 +02:00
Lorenz Leutgeb 05368e84fa cargo: Make schemars a workspace dependency
The `schemars` crate is a dependency of multiple workspace crates in the
same version. Its version number is repeated multiple times in the
respective `*/Cargo.toml` files. This requires more maintenance effort
and risks versions drifting.

As long as all crates depend on the same version, it makes more sense to
have `schemars` as a workspace dependency.

See: <https://doc.rust-lang.org/cargo/reference/workspaces.html#the-dependencies-table>
2025-06-03 15:10:30 +02:00
tippfehlr 9dae540c87 systemd: Provide user service for radicle-node
This file should usually be packaged to `/usr/lib/systemd/user`.
Otherwise, copy it to `/etc/systemd/user`.
2025-06-02 19:47:27 +02:00
Fintan Halpenny 6f25d73d3d build: remove quotes from rust-version
The script would include the quotes and so running `build/build` would
result in:

    $ build/build
    Running build..
    ✓ Radicle key already in ssh-agent
    Building Radicle 1.2.0..
    Creating archive of repository at e9cf91… in build/heartwood-e9cf91….tar.gz..
    Building image (radicle-build-1.2.0)..
    [1/2] STEP 1/17: FROM rust:"1.85"-alpine3.20 AS builder
    Error: creating build container: parsing reference "rust:\"1.85\"-alpine3.20": invalid reference format

Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
2025-06-02 12:28:08 +02:00
Fintan Halpenny e9cf91e1bc cob: bump major version
The addition of the `Namespace` parameter in the traits requires a
major version bump for `radicle-cob`
2025-06-02 11:31:48 +02:00
Fintan Halpenny e6ef767f36 radicle: remove job cob
The Job COB is defined as separate crate: [radicle-job]. So this change removes
its definition and use from the `heartwood` repository.

[radicle-job]: https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z2UcCU1LgMshWvXj6hXSDDrwB8q8M
2025-06-02 10:59:55 +02:00
Fintan Halpenny f4c8ff7a64 chore: prepare crates release
This prepares the crate versions for a new release. The version bumps were
determined by the `cargo-semver-checks` tool.

However, there were some issues with the `radicle-fetch` crate – where when
attempting to check it, it was unable to compile due to the previous version
expecting the kind of `Doc` with a generic parameter. I believe this is due to
the version for `radicle` being specified as simply `0`. This prompted changing
the version specifications to use `major.minor` for all the internal crates.
This, for example, would mean that `radicle-fetch` that relies on `0.15` can use
`>=0.15.0,<0.16.0` – allowing any patch versions but must require a minor
version bump.
2025-05-30 12:58:18 +02:00
Fintan Halpenny caf9e241a6 cli: fix outputs
- `format!` was missing for the `"No seeds found"` message, so the `{rid}` was not being formatted.
- Missing a space between the seed and the timing.
2025-05-30 12:46:48 +02:00
Fintan Halpenny ae1165fa58 build: do not assume `rad` remote
Do not assume the `rad` remote being present, in case other use other naming
remote schemes. Instead, build the remote using the `rad .` and `rad self --nid`
commands.
2025-05-30 12:27:21 +02:00
Fintan Halpenny edcfcae78c build: fix ssh symlinking
The symlinking process of `build/upload` was not working, due to the command
consuming stdin, and ignoring the subsequent targets platforms. Use `-n` to
prevent this, allowing every target binary to be uploaded correctly.

The output is also improved for better feedback during the upload process.
2025-05-30 12:27:13 +02:00
Fintan Halpenny 40e9b7ba3a build: update cargo-zigbuild version to 0.20 2025-05-30 11:17:39 +02:00
Fintan Halpenny 7dcfe45781 build: Dockerfile uses Rust version from `rust-toolchain.toml`
Instead of hardcoding the version of the Rust alpine file, introduce an `ARG` in
the `Dockerfile`. In `build/build`, we determine the version by inspecting
`rust-toolchain.toml`, and pass this value in. This ensures that the binaries
are built using the same toolchain that we develop with.
2025-05-30 11:17:39 +02:00
Fintan Halpenny 924b93283c cli: change announcement message
We ensure that the message of total synced seeds changes when we go over the
replication factor target. This can happen if the node is still waiting to
announce to a preferred seed, and other results are still being returned.
2025-05-30 09:46:53 +02:00
Fintan Halpenny d1ba665ebf radicle: introduce sync::announce tests
Test various cases for the `Announcer` to help ensure correct behaviour.
2025-05-30 09:43:12 +02:00
Fintan Halpenny aa7dcd92db radicle: use a struct to help announce success counts
It is easy to mix up the order of a tuple, so a struct is introduced instead to
ensure that the correct counts are used.
2025-05-30 09:42:08 +02:00
Fintan Halpenny 5a0c14cf61 radicle: ensure preferred seeds are announced to
Ensure that the preferred seeds that are not in the synced set are announced to.
2025-05-30 09:40:50 +02:00
Fintan Halpenny c57d43f2f5 radicle: schemars test should be behind feature flag
A `#[cfg(feature = "schemars")]` was missed in the `profile/config.rs` module
since it was part of the test module.
2025-05-30 09:26:31 +02:00
Fintan Halpenny 5b4cbc2cd8 radicle: introduce announcer
Similar to the `Fetcher` sans-IO approach, an `Announcer` sans-IO approach is
introduced. The previous `Handler::announce` was already quite close to using a
sans-IO approach, but using internally held state. This change makes the
business logic more reusable – and testable.

Similarly to the `Fetcher`, the `Announcer` is configured and then driven by
telling it when nodes have been synchronized with. It will continuously check if
it has reached its target, yielding to the caller to decide whether to keep
going. In contrast, it also provides a way to mark the process as timed out,
since announcing relies on waiting for events to come back in a timely manner.
2025-05-26 12:31:03 +02:00
Fintan Halpenny fa9c6cd142 radicle: move PrivateNetwork to `node::sync`
This construction can be used more generally, for example in announcements, so
it is moved one level up.
2025-05-26 12:31:03 +02:00
Fintan Halpenny cc96b9ed7d cli: improve rad clone
This change improves the `rad clone` command in a few different ways.

The first improvement is to check if the repository already exists before
fetching. If it does exist, then there is no need for the fetch to be performed,
and can move straight to the checkout.

If the repository does not exist, then the fetch is performed, as per usual.
However, it uses a replication factor of 1, so that the fetch finishes as soon
as it has the repository in local storage.

The change also improves the output when failures occur while attempting to
perform the checkout phase. It will print the failure that occurred and provide
a hint message in each case to help debug the failure, or push the caller in the
direction of performing the correct action.

This required some changes in `test/commands.rs` setup. Some tests were using
the `rad-clone.md` to setup a clone, which would have different output if the
repository did not need to be fetched. In those cases, the `rad` method for
performing the clone is used instead.
2025-05-26 11:56:56 +02:00
Johannes Altmanninger 059c804588 radicle: fix build when schemars feature is not enabled
Commit b608a788 (cli: `rad config schema` emits JSON Schema, 2025-04-28)
added a feature flag that enables the "schemars" optional dependency.

Crate radicle-node doesn't use this feature.
Crate radicle fails to compile when the feature is disabled.
This is reproducible with "flake check".
Fix it. 

Note that a "cargo build" of the entire workspace doesn't fail, because the
feature is enabled due to "unification", since "radicle-cli" does use this
feature.  From https://doc.rust-lang.org/cargo/reference/resolver.html#features:

> When building multiple packages in a workspace (such as with --workspace
> or multiple -p flags), the features [of the dependencies] of all of those
> packages are unified. If you have a circumstance where you want to avoid
> that unification for different workspace members, you will need to build
> them via separate cargo invocations.
2025-05-24 22:39:38 +02:00
Lorenz Leutgeb 1a67ac18f3 cli: reword sync replicas help
Reword the help message of `--replicas` and `--max-replicas`, while also
improving the documentation on how the fetch and announce functionality works.
2025-05-23 17:22:48 +01:00
Fintan Halpenny eec4dd4505 radicle: improve sync fetching
This patch changes separates the business logic of fetching from the process of
fetching itself. It does this through a sans-IO approach, where a `Fetcher`
provides the necessary state to help drive a fetch forward, without performing
any of the IO itself.

What the `Fetcher` cares about is:
- What nodes are going to be attempted to be fetched from
- In what order should they be attempted
- When should the fetching process be considered finished

The `Fetcher` is then used in `radicle-cli` to drive forward the `sync::fetch`
function, allowing it to only care about the IO.
2025-05-23 17:22:48 +01:00
Fintan Halpenny c205322c56 node: fix e2e reader limit test
Either error can show up it, according to our wumpus hunter[^0]. Check for both
reasons.

[^0]: https://wumpus.liw.fi/log-f30760d6bb86d2978a5ed4df8ee45b9aa97778b4/log-2025-05-02T03:42:38Z.1885.fail.html
2025-05-22 11:02:34 +02:00
n4ch7 b608a78806 cli: `rad config schema` emits JSON Schema
Leverage `schemars` to generate a JSON Schema from our structs for
configurations and those occurring within them.

The output of `rad config schema` can be used by editors to provide a
smoother editing experience for the configuration file. Discovery
attributes (both keys and values) is greatly improved with the schema
helping in the background.

Refer to:
 - https://json-schema.org
 - https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings
 - https://schemastore.org
2025-05-22 11:00:46 +02:00
Lorenz Leutgeb 5a2f26eaa7 cli/node/status: Redesign
- Print link direction.
 - Shorten NIDs.
 - Use single chars to indicate status, legend is provided via hint.

On nodes with only outgoing connections, link direction won't be very
interesting. But on seed nodes it sometimes *is* of interest in which
direction the connections are going.

Also, I hope that in the future we will enable more and more nodes to
connect directly to each other.

The table header "Dir." is an abbreviation for "Link Direction".
2025-05-22 10:45:32 +02:00
Lorenz Leutgeb ee12f76cbe cli/tests: Fix nextest running via Nix 2025-05-22 10:25:59 +02:00
Fintan Halpenny 9988b63bb2 cob: abstract namespace identifier
This change is to help separate the fact the namespacing by a `NodeId` is a
Radicle specific concern. The identifier can, in theory, be any kind of path
component, as long it is valid in Git.

The motivation for the change is to help separate the idea of a device's
`NodeId` vs an agent being an author – for future agent repository work.
2025-05-22 09:09:57 +02:00
Fintan Halpenny 1f4fcc5e6a radicle: move to `signature` crate
The motivation of this change is to move away from tying signing to be
specifically for ed25519. The reason being that the protocol will want move
towards two different kinds of signing – the node signing artifacts, and an
author signing artifacts.

This change captures the former, node signing, by introducing a `Device` type
that is the `NodeId` – a PublicKey underneath the hood – and a signing
mechanism. This allows the replacement of the `Signer` trait being used – which
always assumed a `PublicKey`. Instead, the `Device` is constructed with
`NodeId`.

In `radicle-cob`, a signer is expected to implement
`signature::Signer<ExtendedSignature>`, and everywhere in `radicle`,
`radicle-node`, `radicle-cli`, and `radicle-remote-helper` is expected the
signer is expected to implement `signature::Signer<Signature>`.

A `Device` implements both of these but only requires
`signature::Signer<Signature>` to do so – since an `ExtendedSignature` is
essentially `(PublicKey, Signature)`, and the `NodeId` of the `Device` can be
used.
2025-05-22 09:09:57 +02:00
Lorenz Leutgeb 41f9048d96 nix: Add flake check that builds at MSRV 2025-05-16 13:49:38 +02:00
Lars Wirzenius 105b65c2ac workspace: set rust-version (MSRV)
This declares the minimum supported Rust version, independently of the
`rust-toolchain.toml` file, which specifies the Rust version and
toolchain components the crate/workspace should be built with. The
MSRV affects other crates that depend on anything in this workspace,
but the toolchain file does not seem to affect them. This means the
MSRV is useful for those who build or develop dependents.

Signed-off-by: Lars Wirzenius <liw@liw.fi>
2025-05-16 13:49:38 +02:00
Fintan Halpenny 9f2c4e3941 chore: use watch_file in .envrc 2025-05-15 14:54:13 +02:00