build(flatpak): net.catcrafts.CrafterReview on the Crafter.Build base
The manifest builds on the Crafter.Build Flatpak (base: net.catcrafts.CrafterBuild): its crafter-build, LLVM 23 and libc++ compile this project inside flatpak-builder, and crafter-build test runs there too. Node 24.22.0 (for the Playwright MCP server) and a static ripgrep 15.2.0 are bundled, pinned by sha256; claude is not, being proprietary. finish-args: the network, the host's files and /tmp, and gnupg's keyboxd socket only, never the agent. The base's files belong to no module of this manifest, so `cleanup` does not reach them: prune-base.sh keeps a named list (the binary, Node, rg, the libc++ the binary links, share/crafter-review, this app's metainfo and licences) and removes the rest, whatever a newer base adds. `crafter-build run flatpak [--base=<branch>] [--jobs=N]` builds it and smoke-tests --version and ldd through `flatpak build`; `run install` installs it as the `local` branch. Until a Crafter.Build release with scripts is on stable, `--base=local` builds against Crafter.Build's own local install, from a gitignored manifest copy whose cache is its own. Built that way: 4 tests green in the sandbox, the charter sha256s the native build prints, no library missing, RUNPATH /app/lib only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
f2b25db50d
commit
b02de3ceff
6 changed files with 334 additions and 1 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -5,4 +5,4 @@ lib/*.a
|
||||||
# written next to the manifest: by CI with the version stamped in, and by
|
# written next to the manifest: by CI with the version stamped in, and by
|
||||||
# `crafter-build run flatpak --base=<branch>` for a local base branch
|
# `crafter-build run flatpak --base=<branch>` for a local base branch
|
||||||
packaging/flatpak/ci-manifest.yaml
|
packaging/flatpak/ci-manifest.yaml
|
||||||
packaging/flatpak/local-base.yaml
|
packaging/flatpak/*-base.yaml
|
||||||
|
|
|
||||||
13
packaging/flatpak/net.catcrafts.CrafterReview.flatpakref
Normal file
13
packaging/flatpak/net.catcrafts.CrafterReview.flatpakref
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
[Flatpak Ref]
|
||||||
|
Title=Crafter Review
|
||||||
|
Name=net.catcrafts.CrafterReview
|
||||||
|
Branch=stable
|
||||||
|
Url=https://flatpak.catcrafts.net/repo/
|
||||||
|
SuggestRemoteName=catcrafts
|
||||||
|
Homepage=https://forgejo.catcrafts.net/Catcrafts/Crafter.Review
|
||||||
|
Comment=Adversarial pre-push review of a frozen commit range
|
||||||
|
Description=crafter-review with its own Node and ripgrep, built on the Crafter.Build toolchain
|
||||||
|
Icon=
|
||||||
|
RuntimeRepo=https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
|
IsRuntime=false
|
||||||
|
GPGKey=GPG_KEY_BASE64_PLACEHOLDER
|
||||||
36
packaging/flatpak/net.catcrafts.CrafterReview.metainfo.xml
Normal file
36
packaging/flatpak/net.catcrafts.CrafterReview.metainfo.xml
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- SPDX-License-Identifier: CC0-1.0 -->
|
||||||
|
<component type="console-application">
|
||||||
|
<id>net.catcrafts.CrafterReview</id>
|
||||||
|
<name>Crafter Review</name>
|
||||||
|
<summary>Adversarial pre-push review of a frozen commit range</summary>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>AGPL-3.0-only</project_license>
|
||||||
|
<developer id="net.catcrafts">
|
||||||
|
<name>Catcrafts</name>
|
||||||
|
</developer>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
The pre-push review pipeline: crafter-review freezes a commit range,
|
||||||
|
partitions it into units, and runs adversarial lenses over it — the
|
||||||
|
approach, the running application through the Playwright MCP server,
|
||||||
|
a bug proof and a security review — one claude process per unit, on the
|
||||||
|
seats the repository provides. A range is send-ready only when every
|
||||||
|
gate passes on the exact frozen hash.
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
<url type="homepage">https://forgejo.catcrafts.net/Catcrafts/Crafter.Review</url>
|
||||||
|
<url type="bugtracker">https://forgejo.catcrafts.net/Catcrafts/Crafter.Review/issues</url>
|
||||||
|
<url type="vcs-browser">https://forgejo.catcrafts.net/Catcrafts/Crafter.Review</url>
|
||||||
|
<provides>
|
||||||
|
<binary>crafter-review</binary>
|
||||||
|
</provides>
|
||||||
|
<content_rating type="oars-1.1"/>
|
||||||
|
<releases>
|
||||||
|
<release version="1.0.0" date="2026-10-31">
|
||||||
|
<description>
|
||||||
|
<p>First release: the pre-push review gates in C++26, shipped as a Flatpak.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
|
</component>
|
||||||
100
packaging/flatpak/net.catcrafts.CrafterReview.yaml
Normal file
100
packaging/flatpak/net.catcrafts.CrafterReview.yaml
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
# SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||||||
|
#
|
||||||
|
# crafter-review as a Flatpak. The runtime is the Freedesktop *Sdk*, as
|
||||||
|
# Crafter.Build's is, not for a compiler but for what a lens runs through its
|
||||||
|
# Bash tool: git, python3 for `python3 -` heredocs, curl, jq and coreutils.
|
||||||
|
# Node (for the Playwright MCP server) and ripgrep (`Bash(rg:*)`, which the Sdk
|
||||||
|
# lacks) are bundled. claude is not: it is a proprietary binary, found in the
|
||||||
|
# host's home where its installers put it, and run inside the sandbox like
|
||||||
|
# everything else, so the memory sampler sees every pass and a pass's whole
|
||||||
|
# tree can be killed.
|
||||||
|
#
|
||||||
|
# The base app is the Crafter.Build Flatpak: its crafter-build, LLVM 23 and
|
||||||
|
# libc++ build this project inside flatpak-builder, so no second LLVM is
|
||||||
|
# built. Everything of it but the libc++ the binary links is pruned at the
|
||||||
|
# end (cleanup-commands below); bump `runtime-version` together with the
|
||||||
|
# base's.
|
||||||
|
app-id: net.catcrafts.CrafterReview
|
||||||
|
runtime: org.freedesktop.Sdk
|
||||||
|
runtime-version: '26.08'
|
||||||
|
sdk: org.freedesktop.Sdk
|
||||||
|
base: net.catcrafts.CrafterBuild
|
||||||
|
base-version: stable
|
||||||
|
command: crafter-review
|
||||||
|
finish-args:
|
||||||
|
# claude to the API, npx to the npm registry, the local stacks on the
|
||||||
|
# host's loopback, and the driver's SQL broker on 127.0.0.1
|
||||||
|
- --share=network
|
||||||
|
# repositories, ~/.claude, ~/.cache/review-gates, ~/.cache/ms-playwright,
|
||||||
|
# ~/.npm: anywhere a developer keeps them. A convenience for a developer
|
||||||
|
# tool, not an isolation boundary.
|
||||||
|
- --filesystem=host
|
||||||
|
# The sandbox's own /tmp is private; this makes /tmp the host's, so a
|
||||||
|
# repository, a config or an artifact under /tmp works as it does natively.
|
||||||
|
- --filesystem=/tmp
|
||||||
|
# freeze reads `%G?`; gnupg with use-keyboxd keeps its public keys behind
|
||||||
|
# this socket. Only this one: the agent, which signs, stays out of reach.
|
||||||
|
- --filesystem=xdg-run/gnupg/S.keyboxd
|
||||||
|
- --env=PATH=/app/bin:/usr/bin
|
||||||
|
modules:
|
||||||
|
- name: ripgrep
|
||||||
|
buildsystem: simple
|
||||||
|
build-commands:
|
||||||
|
- install -Dm755 rg /app/bin/rg
|
||||||
|
sources:
|
||||||
|
- type: archive
|
||||||
|
url: https://github.com/BurntSushi/ripgrep/releases/download/15.2.0/ripgrep-15.2.0-x86_64-unknown-linux-musl.tar.gz
|
||||||
|
sha256: 33e15bcf1624b25cdd2a55813a47a2f95dbe126268203e76aa6a585d1e7b149c
|
||||||
|
|
||||||
|
- name: node
|
||||||
|
# For the Playwright MCP server, which the claude CLI starts through
|
||||||
|
# `npx`. Unpacked whole, with links in /app/bin.
|
||||||
|
buildsystem: simple
|
||||||
|
build-commands:
|
||||||
|
- mkdir -p /app/lib/node /app/bin
|
||||||
|
- cp -a bin include lib share /app/lib/node/
|
||||||
|
- ln -sf ../lib/node/bin/node /app/bin/node
|
||||||
|
- ln -sf ../lib/node/bin/npm /app/bin/npm
|
||||||
|
- ln -sf ../lib/node/bin/npx /app/bin/npx
|
||||||
|
sources:
|
||||||
|
- type: archive
|
||||||
|
url: https://nodejs.org/dist/v24.22.0/node-v24.22.0-linux-x64.tar.xz
|
||||||
|
sha256: cc2f601cee82d9a5a233302fe307abc600727035fd7d2c3a3571755989e95008
|
||||||
|
|
||||||
|
- name: crafter-review
|
||||||
|
buildsystem: simple
|
||||||
|
build-options:
|
||||||
|
# crafter-build fetches Crafter.Network, Crafter.Thread and
|
||||||
|
# Crafter.LintRules from git, each at the commit project.cpp pins.
|
||||||
|
build-args:
|
||||||
|
- --share=network
|
||||||
|
# On this module, not at the top: top-level build options are part of
|
||||||
|
# every module's cache key, and the version changes with every commit.
|
||||||
|
env:
|
||||||
|
# The shipped binary runs on any x86_64 from the last decade.
|
||||||
|
CRAFTER_BUILD_MARCH: x86-64-v2
|
||||||
|
CRAFTER_BUILD_MTUNE: generic
|
||||||
|
# CI replaces this with the version; a local build is a development
|
||||||
|
# build.
|
||||||
|
CRAFTER_REVIEW_VERSION: 0.0.0-dev
|
||||||
|
build-commands:
|
||||||
|
- crafter-build
|
||||||
|
- crafter-build test
|
||||||
|
- install -Dm755 bin/crafter.review-exe-*/crafter-review /app/bin/crafter-review
|
||||||
|
- mkdir -p /app/share/crafter-review && cp -r process /app/share/crafter-review/
|
||||||
|
- install -Dm644 packaging/flatpak/prune-base.sh /app/share/crafter-review/prune-base.sh
|
||||||
|
- install -Dm644 LICENSE -t /app/share/licenses/net.catcrafts.CrafterReview/
|
||||||
|
- install -Dm644 packaging/flatpak/net.catcrafts.CrafterReview.metainfo.xml -t /app/share/metainfo/
|
||||||
|
sources:
|
||||||
|
- type: dir
|
||||||
|
path: ../..
|
||||||
|
skip:
|
||||||
|
- .git
|
||||||
|
- bin
|
||||||
|
- build
|
||||||
|
|
||||||
|
# The base's files are no module's of this manifest, so `cleanup` patterns do
|
||||||
|
# not reach them: the prune keeps a named list and removes the rest.
|
||||||
|
cleanup-commands:
|
||||||
|
- sh /app/share/crafter-review/prune-base.sh
|
||||||
41
packaging/flatpak/prune-base.sh
Normal file
41
packaging/flatpak/prune-base.sh
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
# SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||||||
|
#
|
||||||
|
# The base app, net.catcrafts.CrafterBuild, brings Crafter.Build's whole
|
||||||
|
# toolchain into /app so this project can be built inside flatpak-builder.
|
||||||
|
# The shipped app keeps what crafter-review runs on and nothing else: a list
|
||||||
|
# of what stays rather than of what goes, so whatever a newer base adds goes
|
||||||
|
# without anyone having to know about it.
|
||||||
|
set -eu
|
||||||
|
cd /app
|
||||||
|
|
||||||
|
keep() {
|
||||||
|
case "$1" in
|
||||||
|
bin | bin/crafter-review | bin/node | bin/npm | bin/npx | bin/rg) return 0 ;;
|
||||||
|
lib | lib/node | lib/node/*) return 0 ;;
|
||||||
|
# What a binary built by the base's crafter-build links through its
|
||||||
|
# /app/lib rpath.
|
||||||
|
lib/libc++.so.1* | lib/libc++abi.so.1* | lib/libunwind.so.1*) return 0 ;;
|
||||||
|
# Split into the .Debug extension at export.
|
||||||
|
lib/debug | lib/debug/*) return 0 ;;
|
||||||
|
share | share/crafter-review | share/crafter-review/*) return 0 ;;
|
||||||
|
# Named, not whole: the base's CrafterBuild metainfo and licences go.
|
||||||
|
share/metainfo | share/metainfo/net.catcrafts.CrafterReview.metainfo.xml) return 0 ;;
|
||||||
|
share/licenses | share/licenses/net.catcrafts.CrafterReview | share/licenses/net.catcrafts.CrafterReview/*) return 0 ;;
|
||||||
|
manifest*.json) return 0 ;;
|
||||||
|
esac
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Depth first: a directory comes after its contents, and goes only once it
|
||||||
|
# is empty.
|
||||||
|
find . -mindepth 1 -depth | sed 's|^\./||' | while IFS= read -r path; do
|
||||||
|
keep "$path" && continue
|
||||||
|
if [ -d "$path" ] && [ ! -L "$path" ]; then
|
||||||
|
rmdir "$path" 2>/dev/null || true
|
||||||
|
else
|
||||||
|
rm -f "$path"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
rm -f share/crafter-review/prune-base.sh
|
||||||
143
project.cpp
143
project.cpp
|
|
@ -53,6 +53,146 @@ namespace {
|
||||||
if (described.exitCode != 0 || version.empty()) return "0.0.0-dev";
|
if (described.exitCode != 0 || version.empty()) return "0.0.0-dev";
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The local Flatpak: `crafter-build run flatpak` builds it from this
|
||||||
|
// checkout and `crafter-build run install` installs that build, as
|
||||||
|
// Crafter.Build's own scripts do. --base=<branch> builds on another branch
|
||||||
|
// of the Crafter.Build base app than stable: until a Crafter.Build release
|
||||||
|
// with scripts is on stable, `--base=local` (the branch Crafter.Build's own
|
||||||
|
// `run install` makes) is what builds this project.
|
||||||
|
struct FlatpakPaths {
|
||||||
|
fs::path manifest;
|
||||||
|
// flatpak-builder's downloads, ccache and per-module cache.
|
||||||
|
fs::path state;
|
||||||
|
// The OSTree repo the build is exported to; `install` reads it.
|
||||||
|
fs::path repo;
|
||||||
|
fs::path buildDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Everything under <project>/build/flatpak, a fixed name rather than a
|
||||||
|
// BuildDir(): the Flatpak is compiled by the toolchain inside the sandbox,
|
||||||
|
// not by the host variant. flatpak-builder keys its cache on the
|
||||||
|
// manifest's absolute path, so a branch other than stable gets a manifest
|
||||||
|
// copy of its own next to the original (gitignored), and with it a cache
|
||||||
|
// of its own.
|
||||||
|
FlatpakPaths FlatpakLayout(const fs::path& projectDir, std::string_view base) {
|
||||||
|
const fs::path root = projectDir / "build" / "flatpak";
|
||||||
|
const fs::path packaging = projectDir / "packaging" / "flatpak";
|
||||||
|
return {
|
||||||
|
.manifest = base == "stable" ? packaging / "net.catcrafts.CrafterReview.yaml" : packaging / std::format("{}-base.yaml", base),
|
||||||
|
.state = root / "state",
|
||||||
|
.repo = root / "repo",
|
||||||
|
.buildDir = root / "build-dir",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both scripts drive the host's flatpak, which the sandbox of a Flatpak
|
||||||
|
// crafter-build does not have.
|
||||||
|
bool RefusedInSandbox(std::string_view script) {
|
||||||
|
if (!fs::exists("/.flatpak-info")) return false;
|
||||||
|
std::println(std::cerr, "run {0}: needs the host's flatpak, which the Flatpak build of crafter-build cannot reach. Use a native crafter-build", script);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// flatpak-builder as a host package, else the org.flatpak.Builder app.
|
||||||
|
// Empty when neither is installed.
|
||||||
|
std::string FlatpakBuilder() {
|
||||||
|
if (RunCommandWithTimeout("flatpak-builder --version", std::chrono::seconds(10)).exitCode == 0) return "flatpak-builder";
|
||||||
|
if (RunCommandWithTimeout("flatpak info org.flatpak.Builder", std::chrono::seconds(10)).exitCode == 0) return "flatpak run org.flatpak.Builder";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// A repo path as the file:// URL of a remote. Percent-encoded, because
|
||||||
|
// `remote-modify --url=` stores what it is given as it is.
|
||||||
|
std::string FileUrl(const fs::path& path) {
|
||||||
|
std::string url = "file://";
|
||||||
|
for (const char c : path.string()) {
|
||||||
|
const bool plain = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || std::string_view("/-._~").contains(c);
|
||||||
|
if (plain) {
|
||||||
|
url.push_back(c);
|
||||||
|
} else {
|
||||||
|
url += std::format("%{:02X}", static_cast<std::uint8_t>(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::int32_t BuildFlatpak(ScriptContext& ctx) {
|
||||||
|
if (RefusedInSandbox("flatpak")) return 1;
|
||||||
|
std::string jobs;
|
||||||
|
std::string base = "stable";
|
||||||
|
for (const std::string& arg : ctx.args) {
|
||||||
|
if (arg.starts_with("--base=") && arg.size() > 7) {
|
||||||
|
base = arg.substr(7);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const std::string_view count = arg.starts_with("--jobs=") ? std::string_view(arg).substr(7) : std::string_view();
|
||||||
|
if (count.empty() || !std::ranges::all_of(count, [](char c) { return c >= '0' && c <= '9'; })) {
|
||||||
|
std::println(std::cerr, "run flatpak: unknown argument '{}' (only --jobs=<N> and --base=<branch> are accepted)", arg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
jobs = std::format(" --jobs={}", count);
|
||||||
|
}
|
||||||
|
if (!std::ranges::all_of(base, [](char c) { return std::isalnum(static_cast<std::uint8_t>(c)) || c == '-' || c == '_' || c == '.'; })) {
|
||||||
|
std::println(std::cerr, "run flatpak: '{}' is not a branch name", base);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (RunCommandWithTimeout(std::format("flatpak info net.catcrafts.CrafterBuild//{}", base), std::chrono::seconds(10)).exitCode != 0) {
|
||||||
|
std::println(std::cerr, "run flatpak: the base app is not installed: flatpak install catcrafts net.catcrafts.CrafterBuild//{}", base);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const std::string builder = FlatpakBuilder();
|
||||||
|
if (builder.empty()) {
|
||||||
|
std::println(std::cerr, "run flatpak: neither flatpak-builder nor the org.flatpak.Builder app is installed (flatpak install flathub org.flatpak.Builder)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const FlatpakPaths paths = FlatpakLayout(ctx.projectDir, base);
|
||||||
|
if (base != "stable") {
|
||||||
|
// The manifest with only base-version changed.
|
||||||
|
std::ifstream in(FlatpakLayout(ctx.projectDir, "stable").manifest);
|
||||||
|
const std::string manifest((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
|
||||||
|
constexpr std::string_view Line = "base-version: stable\n";
|
||||||
|
const std::size_t at = manifest.find(Line);
|
||||||
|
if (at == std::string::npos) {
|
||||||
|
std::println(std::cerr, "run flatpak: the manifest has no `{}` line to replace", Line.substr(0, Line.size() - 1));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::ofstream(paths.manifest) << manifest.substr(0, at) << std::format("base-version: {}\n", base) << manifest.substr(at + Line.size());
|
||||||
|
}
|
||||||
|
const std::string buildDir = ShellQuote(paths.buildDir.string());
|
||||||
|
if (const std::int32_t code = ctx.Run(std::format("{}{} --user --force-clean --ccache --state-dir={} --repo={} --default-branch=local {} {}", builder, jobs, ShellQuote(paths.state.string()), ShellQuote(paths.repo.string()), buildDir, ShellQuote(paths.manifest.string()))); code != 0) return code;
|
||||||
|
// The smoke test, through `flatpak build` and not `<builder> --run`:
|
||||||
|
// the org.flatpak.Builder app reports --run's exit status inverted.
|
||||||
|
if (const std::int32_t code = ctx.Run(std::format("flatpak build {} crafter-review --version", buildDir)); code != 0) return code;
|
||||||
|
return ctx.Run(std::format("flatpak build {} sh -c 'ldd /app/bin/crafter-review | grep \"not found\" && exit 1 || exit 0'", buildDir));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::int32_t InstallFlatpak(ScriptContext& ctx) {
|
||||||
|
if (RefusedInSandbox("install")) return 1;
|
||||||
|
if (!ctx.args.empty()) {
|
||||||
|
std::println(std::cerr, "run install: takes no arguments (got '{}')", ctx.args.front());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const FlatpakPaths paths = FlatpakLayout(ctx.projectDir, "stable");
|
||||||
|
if (!fs::exists(paths.repo / "config")) {
|
||||||
|
std::println(std::cerr, "run install: nothing built yet, run: crafter-build run flatpak");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const std::string url = ShellQuote(FileUrl(paths.repo));
|
||||||
|
if (const std::int32_t code = ctx.Run(std::format("flatpak remote-add --user --if-not-exists --no-gpg-verify crafter-review-local {}", url)); code != 0) return code;
|
||||||
|
if (const std::int32_t code = ctx.Run(std::format("flatpak remote-modify --user --url={} crafter-review-local", url)); code != 0) return code;
|
||||||
|
if (const std::int32_t code = ctx.Run("flatpak install --user --noninteractive --or-update crafter-review-local net.catcrafts.CrafterReview//local"); code != 0) return code;
|
||||||
|
if (const std::int32_t code = ctx.Run("flatpak make-current --user net.catcrafts.CrafterReview local"); code != 0) return code;
|
||||||
|
std::println(
|
||||||
|
R"(
|
||||||
|
`flatpak run net.catcrafts.CrafterReview` now starts this build.
|
||||||
|
Back to a published branch, keeping this one installed:
|
||||||
|
flatpak make-current --user net.catcrafts.CrafterReview <branch>
|
||||||
|
Remove it (do this before deleting build/, which holds the repo the remote points at):
|
||||||
|
flatpak uninstall --user net.catcrafts.CrafterReview//local
|
||||||
|
flatpak remote-delete --user crafter-review-local)");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
||||||
|
|
@ -105,5 +245,8 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
||||||
}
|
}
|
||||||
|
|
||||||
LintRules::AddLiteRules(cfg);
|
LintRules::AddLiteRules(cfg);
|
||||||
|
|
||||||
|
cfg.scripts.push_back({"flatpak", BuildFlatpak});
|
||||||
|
cfg.scripts.push_back({"install", InstallFlatpak});
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue