Links: resolve stored paths with craft-docpath's resolve_absolute (#3267)

* Links: use resolve_absolute for stored paths

* CI: release only with git dependencies from storytold

* Release: check git sources from the parsed Cargo.lock and cargo config

The grep let any character stand for the dot in github.com, passed a missing or stale
Cargo.lock, and missed source replacement in .cargo/config.
This commit is contained in:
aiongg
2026-10-23 17:51:28 -04:00
committed by GitHub
parent f02eedd50d
commit 6877d6535f
3 changed files with 42 additions and 5 deletions
+40
View File
@@ -20,7 +20,47 @@ concurrency:
cancel-in-progress: false
jobs:
git-sources:
name: Git dependencies come from storytold
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Git dependencies come from storytold
run: |
set -euo pipefail
test -f Cargo.lock || { echo "Cargo.lock is missing"; exit 1; }
# Source replacement, patches and path overrides in cargo config never show up
# in Cargo.lock. Parsed rather than grepped: TOML has many spellings of one key.
# Cargo still reads the legacy .cargo/config.
python3 - <<'PY'
import os, sys, tomllib
for path in (".cargo/config", ".cargo/config.toml"):
if not os.path.exists(path):
continue
config = tomllib.load(open(path, "rb"))
replaced = [name for name, source in config.get("source", {}).items()
if isinstance(source, dict) and "replace-with" in source]
if replaced or "patch" in config or "paths" in config:
print(f"{path} replaces, patches or overrides a source")
sys.exit(1)
PY
# Fails when Cargo.lock is out of date with the manifests.
cargo metadata --locked --format-version 1 > /dev/null
python3 - <<'PY'
import sys, tomllib
lock = tomllib.load(open("Cargo.lock", "rb"))
bad = sorted({p["source"] for p in lock.get("package", [])
if p.get("source", "").startswith("git+")
and not p["source"].startswith("git+https://github.com/storytold/")})
if bad:
print("Git dependencies outside github.com/storytold:", *bad, sep="\n")
sys.exit(1)
PY
release:
needs: git-sources
# Intentionally tracked at @main (not SHA-pinned) so org-wide CI improvements, security fixes, and build optimizations propagate without PR churn across all craftapp repos.
uses: storytold/craft-common-actions/.github/workflows/release.yml@main
with:
+1 -4
View File
@@ -1184,7 +1184,7 @@ pub(crate) fn document_path_with(
) -> std::result::Result<String, craft_docpath::Refused> {
use craft_docpath::Refused;
let document = document.map(absolute_path);
let resolve = |document: Option<&str>| craft_docpath::resolve(stored, document.map(std::path::Path::new));
let resolve = |document: Option<&str>| craft_docpath::resolve_absolute(stored, document.map(std::path::Path::new));
let path = match resolve(document.as_deref()) {
Err(Refused::Network) => {
let share = document.as_deref().and_then(share).ok_or(Refused::Network)?;
@@ -1192,9 +1192,6 @@ pub(crate) fn document_path_with(
}
path => path?,
};
if !path.is_absolute() {
return Err(Refused::Invalid);
}
path.into_os_string().into_string().map_err(|_| Refused::Invalid)
}
+1 -1
View File
@@ -116,7 +116,7 @@ fn target(h: &str, folder: Option<&str>) -> (String, Option<String>) {
});
match craft_docpath::resolve(&stored, document.as_deref()) {
Ok(path) => {
let file = path.is_absolute().then(|| path.to_string_lossy().into_owned());
let file = craft_docpath::resolve_absolute(&stored, document.as_deref()).ok().map(|p| p.to_string_lossy().into_owned());
let as_written = !file_url && craft_docpath::resolve(&stored, None).as_ref() == Ok(&path);
let link = if as_written { stored } else { path.to_string_lossy().into_owned() };
(link, file)