# `Forecastle.Baseline`
[🔗](https://github.com/ausimian/forecastle/blob/1.0.0/lib/forecastle/baseline.ex#L1)

Resolves the baseline used for relup generation and appup checks.

Baseline specs support three sources:

    rel:_build/prod/rel/my_app/releases/1.0.0/my_app   # an assembled release
    tar:artifacts/my_app-1.0.0.tar.gz                  # a release tarball
    ref:v1.0.0                                         # a git ref, built in a worktree

A path without a prefix means `rel:`. Prefer `tar:` when the deployed artifact
is available. Relups select transitions by version string and cannot verify
that a rebuilt baseline matches the deployed code. Use `ref:` for development
or when no shipped artifact remains.

Generated baselines are cached under `_build/castle/baselines`. Tar entries
are keyed by the copied artifact's digest. Git entries are keyed by commit,
resolution level, `MIX_ENV`, `MIX_TARGET`, and the Elixir and ERTS versions.
Work is staged and renamed into place only when complete.

A `ref:` resolution checks out a linked worktree, builds into the staging
directory, then removes only that worktree registration. It sets
`CASTLE_BASELINE` and refuses recursive baseline builds.

`:compile` resolution builds only compiled modules. `:release` assembles the
complete release. The distinction affects only `ref:` sources.

# `level`

```elixir
@type level() :: :compile | :release
```

How much of the baseline is needed.

`:compile` yields compiled modules, `:release` an assembled release. Only
`:release` guarantees a `:rel_path`.

# `source`

```elixir
@type source() :: :rel | :tar | :ref
```

Where the baseline comes from.

# `t`

```elixir
@type t() :: %Forecastle.Baseline{
  level: level(),
  lib_dir: Path.t(),
  rebuilt?: boolean(),
  rel_path: Path.t() | nil,
  source: source(),
  spec: binary()
}
```

A resolved baseline.

  * `:spec` - the spec exactly as it was given, for diagnostics
  * `:source` - which of the three sources it named
  * `:level` - the level it was resolved at
  * `:rel_path` - the `.rel` file *without* its extension, which is how
    `:systools` names a release. `nil` only for `ref:` at `:compile` level,
    where no release was assembled
  * `:lib_dir` - the directory holding one directory of compiled modules per
    application, matched by `<lib_dir>/*/ebin`
  * `:rebuilt?` - whether the baseline was rebuilt from source rather than
    being the artefact that shipped

# `parse!`

```elixir
@spec parse!(binary()) :: {source(), binary()}
```

Parses a baseline spec into its source and value.

A path without a prefix is treated as `rel:`. Empty values and unknown schemes
raise `Mix.Error`.

# `resolve!`

```elixir
@spec resolve!(binary(), level()) :: t()
```

Resolves a baseline spec at compile or release level.

`rel:` and `tar:` return an existing release. `ref:` builds the revision at
the requested level and caches the result.

# `spec?`

```elixir
@spec spec?(binary()) :: boolean()
```

Returns whether a string begins with a recognised baseline scheme.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
