Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions docs/walkthroughs/make_fossa_deps_conan.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,29 @@ def name_version_of(label: str) -> Tuple[str, str]:
name, version = label.split("/", 1)
return name, version

# Conan recipes may declare `license` as a single string ("MIT") or as a list/tuple of
# strings (["MIT", "Apache-2.0"]). The fossa-deps `license` field must be a single string,
# so a list is joined into one SPDX expression. We use " AND " (every license's obligations
# apply) as the conservative default; change MULTI_LICENSE_JOINER to " OR " if your packages
# are dual-licensed (consumer's choice).
MULTI_LICENSE_JOINER = " AND "
Comment on lines +110 to +115

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Clear documentation and sensible default.

The constant name is descriptive, and the comment clearly explains the normalization rationale and the AND vs OR trade-off. The conservative default (" AND ") is appropriate when license obligations stack.

Optional: Consider adding a note that projects unsure whether their multi-license packages are conjunctive (AND) or disjunctive (OR) should consult their legal/compliance team before changing the joiner.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/walkthroughs/make_fossa_deps_conan.py` around lines 110 - 115, The
documentation is good but should explicitly advise uncertainty consult legal;
update the comment above the MULTI_LICENSE_JOINER constant to add one short
sentence recommending teams consult their legal/compliance group if they're
unsure whether multiple licenses should be joined with " AND " (conjunctive) or
" OR " (disjunctive), keeping the existing rationale and default unchanged and
ensuring the new note mentions MULTI_LICENSE_JOINER so readers can find the
setting to change if needed.


# fossa-deps requires a license string for every custom dependency. When a Conan recipe
# declares no license, fall back to the SPDX "NOASSERTION" marker so the file stays valid;
# emitting a bare `license: null` triggers: expected String, but encountered Null.
NO_LICENSE = "NOASSERTION"

def license_of(node: dict) -> Optional[str]:
return node.get("license")
raw = node.get("license")
if raw is None:
return None
if isinstance(raw, str):
return raw or None
if isinstance(raw, (list, tuple)):
parts = [str(item).strip() for item in raw if item is not None and str(item).strip()]
return MULTI_LICENSE_JOINER.join(parts) if parts else None
# Unexpected shape (number, dict, ...): coerce to a string so fossa-deps stays valid.
return str(raw)

def homepage_of(node: dict) -> Optional[str]:
candidate = node.get("homepage")
Expand Down Expand Up @@ -158,7 +179,7 @@ def mk_fossa_deps(graph):
vendored_deps.append(FossaVendorDep(name, version, src_dir))
else:
logging.info(f"could not find source code in disk for: {label}, using this as vendored dependency for fossa-deps")
custom_deps.append(FossaCustomDep(name, version, license, FossaCustomDepMetadata(homepage, description)))
custom_deps.append(FossaCustomDep(name, version, license or NO_LICENSE, FossaCustomDepMetadata(homepage, description)))

fossa_dep_yml = FossaDep(vendored_deps, custom_deps)
fossa_dep_yml.dump()
Expand Down
Loading