Skip to content

Commit

Permalink
Add lockfile docs (#829)
Browse files Browse the repository at this point in the history
commit-id:f9649934

---

**Stack**:
- #830
- #829⚠️ *Part of a stack created by [spr](https://github.com/ejoffe/spr). Do
not merge manually using the UI - doing so may have unexpected results.*
  • Loading branch information
maciektr authored Oct 27, 2023
1 parent 1cede5d commit c77101e
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 3 deletions.
1 change: 1 addition & 0 deletions website/.vitepress/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const sidebar = {
p("Conditional compilation", "/docs/reference/conditional-compilation"),
p("Global directories", "/docs/reference/global-directories"),
p("Manifest", "/docs/reference/manifest"),
p("Lockfile", "/docs/reference/lockfile"),
p("Workspaces", "/docs/reference/workspaces"),
p("Profiles", "/docs/reference/profiles"),
p("Scripts", "/docs/reference/scripts"),
Expand Down
5 changes: 2 additions & 3 deletions website/docs/guides/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ that Alexandria is a collection of multiple packages, and we will use `alexandri
alexandria_math = { git = "https://github.com/keep-starknet-strange/alexandria.git" }
```

In fact, it is always good to pin Git dependencies to concrete commits, otherwise Scarb would try to update this
dependency each time it is executed.
You can achieve this using one of the following extra fields that you can pass along `git`: `branch`, `tag` and `rev`.
You can pin a Git dependency to concrete commit, branch or a tag using one of the following extra fields that can be
passed along `git`: `branch`, `tag` and `rev`.

Actually this is how the OpenZeppelin Contracts for Cairo library is released, since the `main` branch is not stable.

Expand Down
111 changes: 111 additions & 0 deletions website/docs/reference/lockfile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# The `Scarb.lock` lockfile

_Lockfiles_ are a common mechanism that allows package manager to lock dependencies to concrete versions, ensuring
reproducible builds.

## Scarb.toml vs Scarb.lock

`Scarb.toml` and `Scarb.lock` serve two different purposes.

`Scarb.toml` is about describing your dependencies in a broad sense, and is written by you.
`Scarb.lock` is a file that captures the exact version of every dependency used in a workspace or package.
It is maintained by Scarb and should not be manually edited.

## Why reproducible builds are important?

When [specifying project dependencies](specifying-dependencies.md), rather than pointing to specific versions of
packages you want to rely on, you define version requirements.
Usually, those requirements can accept multiple versions.
For instance, specifying `1.2.3` would allow all versions `>=1.2.3` and `<2.0.0`.
Similarly, the following specification can be resolved to more than one commit hash:

```toml
alexandria_math = { git = "https://github.com/keep-starknet-strange/alexandria.git", branch = "next" }
```

Without lockfile mechanism, Scarb would always pull the latest commit from the branch `next`, which may change between
Scarb runs.
Consequently, we would not be able to ensure that Scarb builds are reproducible, i.e. two subsequent `scarb build`
calls would produce the same results using the same source code.
This is not ideal, as some regressions or incompatibilities may be introduced in the new changes of packages from
dependency.
Additionally, for security reasons users should be able to control what changes are pulled to their builds.
Consequently, users often would have to manually lock their dependency revisions, e.g. by specifying the commit hash from
the dependency package repository in the manifest file, which is tedious and error-prone.

## How lockfiles work?

Lockfiles automatically lock dependencies to a certain revisions, by writing resolved versions to a file beside
the project manifest.
This file is called `Scarb.lock`.
It's then read before Scarb resolves dependencies, and locked versions are used by the resolver.
If you change your dependencies specification in the manifest file, lockfile will change as well.
Lockfiles contain exact specifications of all packages from full tree of dependencies (including dependencies of
dependencies etc.).
Scarb lockfiles can easily be reviewed by the user.

::: info
Lockfiles should be committed to version control system (e.g. a Git repository),
allowing for full tracking of concrete version changes.
:::

## Lockfile format

The lockfile is a TOML file, which starts with comment containing an auto-generated file marker and a version field.
The version field is used to distinguish between different lockfile formats.
For now, this will always state `1`.

Then, a list of package metadata entries are printed as TOML objects.
The list is sorted alphabetically by package name.
Each entry contains the following fields:

- `name` - name of the package, as in [Scarb.toml manifest](./manifest.md#name)
- `version` - version of the package, as in [Scarb.toml manifest](./manifest.md#version)
- `source` - the string representation of the source of the package.
- `dependencies` - a list of names of packages that this package depend on.
This field is omitted if the package has no dependencies.

Note that each package can be listed only once, even if it is used by multiple other packages.
This is a direct consequence of the fact, that Cairo compilation model does not accommodate multiple versions
of the same package.

For instance, if a package with following manifest is created:

```toml
[package]
name = "hello_world"
version = "0.1.0"

[dependencies]
alexandria_math = { git = "https://github.com/keep-starknet-strange/alexandria.git" }
alexandria_data_structures = { git = "https://github.com/keep-starknet-strange/alexandria.git" }

```

The resulting lockfile will look like this:

```toml
# Code generated by scarb DO NOT EDIT.
version = 1

[[package]]
name = "alexandria_data_structures"
version = "0.1.0"
source = "git+https://github.com/keep-starknet-strange/alexandria.git#3356bf0c5c1a089167d7d3c28d543e195325e596"

[[package]]
name = "alexandria_math"
version = "0.2.0"
source = "git+https://github.com/keep-starknet-strange/alexandria.git#3356bf0c5c1a089167d7d3c28d543e195325e596"
dependencies = [
"alexandria_data_structures",
]

[[package]]
name = "hello_world"
version = "0.1.0"
dependencies = [
"alexandria_data_structures",
"alexandria_math",
]
```

0 comments on commit c77101e

Please sign in to comment.