Contributing
The development environment
Section titled “The development environment”To get started, clone this repository and allow devenv to set up the
environment with the configuration from the ./dev directory:
git clone ssh://git@codeberg.org/tarcisio/conan-flake.gitcd conan-flakedevenv --from path:dev allowIt will complain that conan-flake is not available:
error: To use 'conan', run the following command:
$ devenv inputs add conan-flake git+https://codeberg.org/tarcisio/conan-flakeAdd the conan-flake input pointing to the local checkout (the root of this
repository) and activate devenv shell:
devenv inputs add conan-flake "git+file://$PWD"devenv shellPoint that input at the checkout as a git reference rather than as
path:"$PWD". A path: input is copied off disk verbatim, .gitignore and
all, and Nix can only archive regular files, directories and symbolic links —
so a socket or a device node left in the working tree by some local tool aborts
the fetch outright with has an unsupported type, whether or not the process
that made it is still alive. git+file:// copies the tree through git, which
leaves ignored files behind, and it resolves to the same store path as the .
reference the justfile recipes override this input with. It also inherits
git’s view of the tree: a file that has never been git added is invisible to
the fetch.
Check that a default Conan profile was configured successfully:
conan profile showHost profile:[settings]arch=x86_64build_type=Releasecompiler=gcccompiler.cppstd=20compiler.libcxx=libstdc++11compiler.version=15.3.0os=Linux[platform_tool_requires]cmake/4.3.4[conf]
Build profile:[settings]arch=x86_64build_type=Releasecompiler=gcccompiler.cppstd=20compiler.libcxx=libstdc++11compiler.version=15.3.0os=Linux[platform_tool_requires]cmake/4.3.4[conf]Commands can also be run without entering the shell interactively, by prefixing
them with devenv shell --. To pick a different secretspec provider when
activating it:
devenv inputs add conan-flake "git+file://$PWD"devenv --secretspec-provider dotenv shellRunning the checks
Section titled “Running the checks”The justfile
recipes all point nix at ./dev and override the conan-flake input with the
local checkout:
just show # nix flake show ./devjust check # nix flake check ./devjust repl # nix repl ./devjust ci # the full local CI, via `vira`just vira <args> # `vira` with arbitrary argumentsjust search <query> # conan search "<query>" (defaults to "*")just show and just check also accept a path or flake reference, so a single
scenario can be targeted:
just check ./examples/flake-partsEach directory under examples and test is an independent flake, and can be validated in isolation against the local checkout:
nix flake check ./examples/flake-parts --override-input conan-flake . --show-trace --no-pure-evalMost examples define a checks.test derivation that runs conan install and
conan build inside a simulated shell, so nix flake check is the whole test
runner — there is no separate one.
vira.hs
is the source of truth for which example and test flakes CI exercises: a new
scenario under examples/ or test/ has to be added to its build.flakes list
to be checked. The pipelines themselves are in
.woodpecker:
checks.yml runs nix flake check ./dev, then vira ci -b, then a build of
flake.parts-website against this repository, which is what publishes the
option reference; release.yml
runs vira ci -b again on release events.
The documentation site
Section titled “The documentation site”This site is an Astro project living under
docs, themed
with Starlight. Its sources are the Markdown
files under docs/src/content/docs, one per chapter. From the development
shell:
just docs # build the site, exactly as CI builds itjust docs-serve # serve it locally, reloading on every source changeNeither command installs anything: the development shell puts the site’s npm
dependencies at docs/node_modules, installed by Nix from the committed
docs/pnpm-lock.yaml.
A new page is a new Markdown file under docs/src/content/docs, with a
title in its frontmatter, listed in the sidebar of
docs/astro.config.mjs.
That list is what Starlight renders into the navigation of every page, and a
chapter missing from it is a chapter nothing links to. Chapters link to each
other by their source path ([Toolchains](./toolchains.md)), which keeps the
link working while reading the sources on Codeberg; a rehype plugin
(docs/plugins/rehype-rewrite-links.mjs) rewrites those targets to the page
URLs the built site serves.
just docs builds through Nix, from a filtered copy of the sources, and its
output carries the site alone. just docs-serve runs the Astro development
server over the checkout instead, which is also what watches the sources and
reloads the page being read.
How the generated blocks are refreshed
Section titled “How the generated blocks are refreshed”Code samples are never written into the Markdown sources by hand. Each one is
declared by an embedmd marker naming
the example file and the region to take, and the fenced block below the marker
is rewritten from that file:
[embedmd]:# (./.examples/flake-parts/flake.nix nix !/.*{ inputs/ !/.*inputs }/ s/# // dedent)embedmd resolves the path relative to the Markdown file and refuses to leave
that directory, which is why the site’s markers go through
docs/src/content/docs/.examples, a symbolic link to the examples directory
at the root of the repository.
Running embedmd over the sources rewrites every such block in place:
embedmd README.md docs/src/content/docs/*.mdThat same command runs as a pre-commit hook and as a treefmt formatter, so
in practice the blocks are refreshed on commit, and a sample that no longer
matches its example project fails the authoring.EMBEDDING.2 check in CI —
the checks over the site are named after the requirement each one proves.
Command-output blocks are generated the same way, by
mdsh: the command that produces the output
is recorded next to the block, either visibly —
```sh > text $conan profile show```
<!-- BEGIN mdsh -->```text…output…```<!-- END mdsh -->— or hidden, when the command is scaffolding rather than something the reader would type:
<!-- > $echo '```text'cd "$(git rev-parse --show-toplevel)/examples/flake-parts"nix develop --command bash -c "profile-show-wrapper 2>/dev/null"echo '```'-->mdsh runs each block from the directory of the Markdown file that carries it,
which is why the site’s blocks cd to the repository root first. Running it
replaces the block that follows with the command’s current output:
mdsh --inputs docs/src/content/docs/*.mdThe sources of the site are the whole of that list: README.md is a pointer at
this site and carries no command-output block, so it is off
programs.mdsh.includes in
dev/treefmt.nix.
It does keep one embedded sample, which is why it is still named in the
embedmd command above.
Publishing the site
Section titled “Publishing the site”This site is a Codeberg Page of
this repository: the content of its pages branch is served at
https://tarcisio.codeberg.page/conan-flake/. One command builds the site and
updates that branch from the build:
just docs-publishIt runs
scripts/publish-pages.sh,
which is also what CI runs, so what a contributor publishes and what a pipeline
publishes are produced by the same code. It needs no credential beyond the one
that already pushes to this repository: the push goes through the checkout’s own
origin.
What it does, and why it does it that way:
- the site is built first, and nothing else happens if that build fails, so a broken build cannot leave a half-published branch behind;
- the branch is updated through a temporary git worktree, never by switching this checkout, so the branch that was checked out stays checked out and the working tree is not touched — including when the run fails;
pagesis created as an orphan branch: it carries no source of the repository and its history starts at a root commit of its own;- everything the branch carried is dropped before the new build is copied in, so a page removed from the site stops being served;
- the build output is copied out of the Nix store dereferencing symbolic links and without the store’s permissions, since a store path is read-only and its links point back into a store no visitor has. What lands on the branch is the output of the site’s derivation, whole: the server builds nothing.
The pipeline that runs the same script from main is
.woodpecker/pages.yml.
A push to main that touches the sources the site is built from publishes it,
and the pipeline can still be run on demand, which is how the site is
republished without a commit. The checklist below is how that was set up.
When two publications race, the second push loses: its run fails on a rejected push, and the site goes on carrying the other run’s build until the next change or a manual run.
Switching publication on
Section titled “Switching publication on”These steps need administration rights on the Codeberg repository and on its
Woodpecker project, so they cannot be done from a checkout. All of them have
been taken here: the webhook and the codeberg_token secret are registered,
https://tarcisio.codeberg.page/conan-flake/ serves this site from the pages
branch, and CI publishes it on every change to its sources on main. They are
kept because they are what a fork, or a move to another forge, has to repeat
— and a fork has to repeat them before its pages workflow runs at all:
the publishing step names codeberg_token, and a workflow whose secret
Woodpecker cannot resolve fails to compile rather than reporting that nothing
was published.
- Register the webhook. Repository settings → Webhooks → Add
webhook → type Forgejo, with
Target URL
https://tarcisio.codeberg.page/conan-flake/— which doubles as the address the site is served from — and Branch filterpages. This is what tells git-pages to pull the branch when it is pushed. - Do not read a failed test delivery as a broken setup. The “Test delivery” button fails by design; Codeberg’s own documentation says so. Verify by pushing the branch and loading the site instead.
- Create the push credential. A Codeberg access token with write access
to this repository, belonging to the account the pipeline pushes as
(
tarcisio, or whateverPAGES_USERinscripts/publish-pages-ci.shnames), stored as a secret named exactlycodeberg_tokenon this repository’s Woodpecker project..woodpecker/pages.ymlreads it, and publishes nothing while it is empty. - Allow that secret at both events the pipeline runs on. Open the secret
and tick
pushandmanualunder “Available at the following events”. Woodpecker offers a secret only to a run whose event the secret lists, and a new secret listspush,taganddeployment— somanualhas to be added, andpushhas to be left ticked. It resolves secrets while compiling the workflow, before anything runs, so a missing event does not fail a step: it fails the whole run, withsecret "codeberg_token" is not allowed to be used with pipeline event "push"(or"manual"). This is the one step of this checklist that cannot be taken from a checkout, and the one to take before the commit that turns publishing on, or that very push is the run that fails. - Publish once, with
just docs-publishfrom a checkout. That first run is what creates thepagesbranch, and it uses your own push credentials rather than the secret. - Publish from CI on demand. Once
codeberg_tokenexists and allowsmanual, run thepagespipeline of themainbranch from Woodpecker’s interface: that publishes the site, with no commit to make. This is still how the site is republished when the sources did not change. - Let CI publish on every change.
.woodpecker/pages.ymlhas a single step,pages, which runs on- event: [push, manual]: a push tomaintouching the paths the workflow filters on publishes the site, and so does a run started by hand. There is no second, tokenless step beside it — on a push that one would run the publishing wrapper again without a credential and announce that nothing was published next to a successful publication. What keeps unrelated pushes from publishing is the workflow’s ownwhen, which was already filtering onmainand on the site’s sources. The ordering matters: thecodeberg_tokensecret has to allow thepushevent before the commit that makes this change lands, or that push is compiled with a secret it may not read and fails before it starts. - Verify. Load https://tarcisio.codeberg.page/conan-flake/; content
can take a few minutes to refresh. If it does not appear, ask git-pages
what it deployed, with
curl https://tarcisio.codeberg.page/conan-flake/.git-pages/manifest.json— the manifest names the repository, the branch and the commit it served the site from.
A path the site does not carry is answered with the site’s own 404.html, which
Astro generates at the root of the output and links back into the sub-path the
site is built for (base in docs/astro.config.mjs).