Compare commits

..
Author SHA1 Message Date
Dylan M. Taylor 1c00ae3492 security: write the release from the release job only (SonarCloud S8233)
The workflow-level contents: write granted every job the right to push
tags and releases; the reusable release workflow is the only job that
needs it. Workflow level drops to read.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-10-23 17:16:13 -04:00
Dylan M. Taylor c1dd60ffd6 Merge pull request #2018 from dylanmtaylor/ci/sonar-main-not-cancelled
ci(sonar): stop cancelling main-branch runs so coverage is published
2026-10-23 16:58:56 -04:00
Dylan M. Taylor bec28d6b87 ci(sonar): don't cancel superseded runs on main, so coverage is published 2026-10-23 16:50:42 -04:00
aiongg d3e6111cf1 Xrefs and data links: resolve stored paths with craft-docpath's resolve_absolute (#1750)
* Xrefs and data links: use resolve_absolute for stored paths

* CI: check that git dependencies come from storytold

* CI: release only with git dependencies from storytold

* Parse Cargo.lock as TOML when checking git sources

* Use the shared git-sources check in CI

* Parse cargo config, legacy .cargo/config included, in the git-sources check
2026-10-23 16:42:01 -04:00
aiongg dd1f0531ac i18n: missing translations never fail; cargo xtask i18n reports them (#2013) 2026-10-23 15:40:12 -04:00
aiongg 37150774c6 CI: run the gate through craft-common-actions' shared gate.yml; FreeBSD nightly and on release (#1987)
ci.yml is new: it calls the shared workflow (cached apt packages, nextest, main-only cache saves, Cargo.lock check). FreeBSD and Windows ARM64 run nightly and on pushes to release instead of on pull requests. Depends on storytold/craft-common-actions#69.
2026-10-23 13:56:16 -04:00
aiongg 9cf115e808 CI: one test binary per crate, nextest, line tables only (#1989)
* Build: line tables only in dev, no debug info for dependencies

* Tests: one integration-test binary per crate

Each crate's tests/*.rs becomes a module of tests/it/main.rs. Files that
install process-wide state (the file io hooks, user aliases, SAVETIME and
SAVEFILEPATH, user linetype and pattern files, registered fonts) stay their
own test binaries.

* xtask ci: nextest, tests without examples, one wasm check call
2026-10-23 13:34:26 -04:00
288 changed files with 670 additions and 1007 deletions
+30
View File
@@ -0,0 +1,30 @@
name: CI
# Quality gates for every push to main and every pull request (`cargo xtask ci`), through the
# suite's shared gate workflow in craft-common-actions.
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
# A newer push to a PR branch cancels its older run; every push to main runs to the end.
concurrency:
group: ci-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
gate:
# Tracks @main so suite-wide CI fixes reach every app without a PR in each repository.
uses: storytold/craft-common-actions/.github/workflows/gate.yml@main
with:
# Same craft-fonts commit as release.yml.
craft-fonts-ref: 3d9ab3a132ed0eff457e424226a435a901da30d3
timeout-minutes: 90
packages: >-
pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcb1-dev libxcursor-dev
libxrandr-dev libxi-dev libfontconfig1-dev libfreetype-dev mesa-vulkan-drivers
libgl1-mesa-dev
+3
View File
@@ -2,6 +2,9 @@
# (GitHub has no FreeBSD runners). GPU tests skip themselves when the VM has no adapter.
name: FreeBSD
# The VM build is slow, so it runs nightly on main and on pushes to `release`, not on every pull
# request: a drifted dependency still shows up within a day, and always before a release ships.
# PRs that change the FreeBSD workflow or packaging itself still run it.
on:
push:
branches: [release]
+38
View File
@@ -21,3 +21,41 @@ jobs:
nix:
# 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/nix.yml@main
git-sources:
name: Git dependencies come from storytold
runs-on: ubuntu-latest
timeout-minutes: 5
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
+44 -1
View File
@@ -11,14 +11,57 @@ on:
default: ""
permissions:
contents: write
contents: read
concurrency:
group: release-${{ github.ref }}
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
permissions:
# The reusable release workflow tags and uploads the draft release.
contents: write
# 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:
+2 -1
View File
@@ -11,7 +11,8 @@ permissions:
concurrency:
group: sonarcloud-${{ github.ref }}
cancel-in-progress: true
# A push to main is the run that publishes coverage; superseded runs there would never finish.
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
sonarcloud:
+4 -2
View File
@@ -3,15 +3,17 @@
# binaries are ARM64, run the CLI natively, and uninstall.
name: Windows ARM64
# Nightly on main and on pushes to `release` (dependency and runner-image drift shows up within a
# day, and always before a release ships), and on PRs that change the Windows packaging itself.
on:
schedule:
- cron: "3 5 * * *"
push:
branches: [release]
pull_request:
paths:
- .github/workflows/windows-arm64.yml
- packaging/windows/**
schedule:
- cron: "41 3 * * 1"
workflow_dispatch:
concurrency:
Generated
+2 -2
View File
@@ -2212,9 +2212,9 @@ dependencies = [
[[package]]
name = "lyon_tessellation"
version = "1.0.23"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd4872650e70dc907dd4f7ebc449d7d657a0d2658e423b2e724970870bbbf75b"
checksum = "43b8dcf906637ecef61b3c0740c7a4e7f27caeb31257cfac0cc579ce15be6005"
dependencies = [
"float_next_after",
"lyon_path",
+2
View File
@@ -69,9 +69,11 @@ type_complexity = "allow"
[profile.dev.package."*"]
opt-level = 2
debug = false
[profile.dev]
opt-level = 1
debug = "line-tables-only"
[profile.release]
opt-level = 3
+6
View File
@@ -0,0 +1,6 @@
mod cli;
mod drafting_spacing;
mod help;
mod mcp_connect;
mod skipped_records;
mod undrawn_entities;
+2
View File
@@ -0,0 +1,2 @@
mod lin_pat_parse;
mod sub_segment_alias;
+1 -2
View File
@@ -18,8 +18,7 @@ pub use craft_docpath::Refused;
/// on other platforms.
pub fn resolve(stored: &str, document: Option<&Path>) -> Result<PathBuf, Refused> {
let document = document.filter(|d| !d.as_os_str().is_empty()).map(|d| std::path::absolute(d).unwrap_or_else(|_| d.to_path_buf()));
let path = craft_docpath::resolve(stored.trim(), document.as_deref())?;
if path.is_absolute() { Ok(path) } else { Err(Refused::Invalid) }
craft_docpath::resolve_absolute(stored.trim(), document.as_deref())
}
#[cfg(test)]
@@ -29,7 +29,7 @@ fn session() -> (Session, Handle) {
/// As [`session`], with the fixture's text changed by `edit` first.
fn session_with(edit: impl Fn(String) -> String) -> (Session, Handle) {
let grip = "0 BLOCKLINEARGRIP\n5 68\n330 61\n100 AcDbEvalExpr\n90 9\n98 33\n99 232\n100 AcDbBlockElement\n300 End Grip\n98 33\n99 232\n1071 0\n";
let src = include_str!("../../io/tests/data/dynblock_door.txt")
let src = include_str!("../../../io/tests/data/dynblock_door.txt")
.replace("\r\n", "\n")
.replace("170 4\n91 0\n91 0\n", "170 4\n91 8\n91 9\n")
.replace("1030 0\n93 0\n170 0\n171 0\n100 AcDbBlockVisibilityParameter", "1030 0\n93 10\n170 0\n171 0\n100 AcDbBlockVisibilityParameter")
@@ -2,7 +2,6 @@
//! leave exactly the expected entities, layers and printed text. The corpus lives in its own
//! repository; point `CADCRAFT_LISP_CORPUS` at its `cases` directory (or the repository) to run
//! it. Without it the test only says so.
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use std::path::{Path, PathBuf};
+143
View File
@@ -0,0 +1,143 @@
mod angle_prompts;
mod angle_settings;
mod annotate_options;
mod annotative;
mod arc_ctrl_direction;
mod array_commands;
mod assoc_array;
mod attdisp_attsync;
mod attedit_prompts;
mod attrib_modes;
mod attrib_props;
mod attribute_tools;
mod block_keep;
mod block_redefine;
mod break_closed_polyline;
mod break_join_locked_layers;
mod break_keeps_z;
mod burst;
mod constraint_geometry;
mod constraint_infer;
mod count;
mod dash_block;
mod data_extraction;
mod dim_baseline_spacing;
mod dim_chain;
mod dim_commands;
mod dim_explode_text;
mod dim_properties;
mod dim_radial_inside;
mod dim_radial_outside;
mod dim_vars;
mod dimtedit_prompts;
mod drafting_spacing;
mod draw_prompts;
mod draworder;
mod dyn_input;
mod dynamic_block_data;
mod dynamic_grips;
mod fillet_chamfer;
mod fix_holds_grips;
mod followups_626;
mod grip_dim_input;
mod grip_options;
mod grip_selection;
mod group_selection;
mod groups;
mod hatch_assoc;
mod hatch_dialog_helpers;
mod hatch_numeric_validation;
mod hatch_options;
mod helix;
mod inquiry_keywords;
mod inquiry_z;
mod insert_prompts;
mod isometric;
mod join_close;
mod json_param_validation;
mod layer_cmdline;
mod layer_merge_delete;
mod layoff_repeat;
mod layout_prompts;
#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
mod lisp_corpus;
mod malformed_handles;
mod matchprop;
mod measure_distance_snapping;
mod metric_linetypes;
mod mleader_content;
mod mleader_remember;
mod mline;
mod mocoro;
mod modify_curves;
mod mtext_columns;
mod mtext_options;
mod multiline_attributes;
mod named_views;
mod non_finite_edits;
mod offset_closed_spline;
mod offset_ellipse_side;
mod offset_move;
mod options_profile;
mod overkill;
mod parallel_display_list;
mod pedit_splinedit;
mod pick_text;
mod pickdrag;
mod pline_arc_xline_options;
mod plot_styles;
mod point_modifiers;
mod post_command_passes;
mod prompt_keywords;
mod props_bad_lineweight;
mod props_insert_scale_attribs;
mod purge_mlinestyles;
mod purge_prompts;
mod qdim;
mod qdim_modes;
mod query_entities;
mod quickcalc;
mod recent_commands;
mod rectang_ortho;
mod refedit;
mod region;
mod rename_cmdline;
mod rotate_reference;
mod select_keywords;
mod select_similar;
mod select_underscore_keywords;
mod selection_cycling;
mod selection_modes;
mod setvar_coverage;
mod shapes;
mod snap_annotations;
mod snap_blocks;
mod snap_curves;
mod snap_intersections_aperture;
mod snap_nearest;
mod snap_overrides;
mod snap_tracking;
mod snaps_more;
mod space_is_enter;
mod spline_degree;
mod spline_options;
mod stretch;
mod stretch_select;
mod table_formulas;
mod table_styles;
mod temp_tracking;
mod text_commands;
mod text_left_justify;
mod tolerance;
mod transparent;
mod trim_closed_polyline;
mod trim_extend_options;
mod undo_count;
mod undo_layout_tab;
mod viewport_clip;
mod vplayer_prompts;
mod vports;
mod xdata_follows_entity;
mod zoom_keywords;
mod zoom_viewport;
mod zoom_window_ortho;

Some files were not shown because too many files have changed in this diff Show More