test: update packaging tests#163
Conversation
|
@coderabbitai resolve |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 Walkthrough개요이 PR은 보안 스캔 워크플로우 추가, 버전 0.1.1 릴리스, 음악 분석 엔진의 화음/음역대/분리 DSP 모듈 도입, 프론트엔드 JSDoc 문서화, 그리고 지원 인프라 업데이트를 포함합니다. 변경사항
Sequence Diagram새로운 분석 기능들은 주로 데이터 구조/검증 변경이고, 핵심 ML 통합은 기존 파이프라인 내 보조 단계이므로, 시퀀스 다이어그램이 필수 조건을 충족하지 않습니다. 코드 리뷰 예상 소요 시간🎯 4 (복잡) | ⏱️ ~50분 연관된 PR
추천 라벨
시
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 26
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
services/analysis-engine/tests/test_release_packaging.py (1)
111-149:⚠️ Potential issue | 🔴 Critical
main()테스트 전제와 실제 구현이 충돌합니다.Line 111-149 테스트는 DMG 산출물만 준비하고
.dmg.manifest.txt를 기대하지만, 실제main()은 binary/frontend dist/metadata 파일 존재를 먼저 강제하고, 생성물도.zip+.manifest.txt규칙입니다. 현재 테스트는FileNotFoundError또는 경로 불일치로 실패합니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@services/analysis-engine/tests/test_release_packaging.py` around lines 111 - 149, The test test_release_packaging_main_writes_arch_specific_manifest sets up only a DMG artifact but the implemented packaging.main() currently requires other artifacts (binary/frontend dist/metadata) and emits .zip + .manifest.txt names, so update packaging.main() (in package_desktop_artifact_main) to accept the DMG-only case and produce an architecture-specific .dmg.manifest.txt when BANDSCOPE_ARTIFACT_OS== "macos" and BANDSCOPE_ARTIFACT_ARCH=="arm64": detect the target triple/env vars, look for the .dmg under the same target bundle path (aarch64-apple-darwin/.../bundle/dmg/App.dmg), skip or make optional the checks for other dist files when a .dmg exists, and write the manifest file named bandscope-macos-arm64-<GITHUB_SHA_PREFIX>.dmg.manifest.txt with platform and arch lines so the test's expected manifest path and contents are produced.apps/desktop/src/App.tsx (1)
126-132:⚠️ Potential issue | 🟠 MajorYouTube URL을 IPC 호출 전에 정규화/검증하세요.
현재 입력 문자열이
trim/URL 파싱 없이 그대로 전달되어 공백 입력이나 비정상 스킴 문자열이 하위 계층으로 내려갑니다. 최소한trim()+new URL()검증 후http/https만 허용하는 가드가 필요합니다.🔧 제안 수정안
const handleImportYoutube = async () => { setSelectionError(null); + const normalizedUrl = youtubeUrl.trim(); + if (!normalizedUrl) { + setSelectionError(t("youtubeImportFailed")); + return; + } + + let parsedUrl: URL; + try { + parsedUrl = new URL(normalizedUrl); + } catch { + setSelectionError(t("youtubeImportFailed")); + return; + } + if (parsedUrl.protocol !== "https:" && parsedUrl.protocol !== "http:") { + setSelectionError(t("youtubeImportFailed")); + return; + } + setIsImporting(true); try { - const selection = await importYoutubeUrl(youtubeUrl); + const selection = await importYoutubeUrl(normalizedUrl); if (selection.ok) { setSelectedBootstrap(selection.bootstrap); setYoutubeUrl("");As per coding guidelines "Treat files, URLs, metadata, model artifacts, and project files as untrusted input".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/App.tsx` around lines 126 - 132, handleImportYoutube currently passes raw youtubeUrl down to importYoutubeUrl/IPC; trim and validate it first: call const raw = youtubeUrl?.trim() and if empty setSelectionError and return; then try to construct new URL(raw) and ensure url.protocol is "http:" or "https:" (otherwise setSelectionError and return). Only after these guards call importYoutubeUrl with the validated URL string; keep existing setIsImporting/setSelectionError flows and reference handleImportYoutube, importYoutubeUrl, youtubeUrl, setSelectionError, and setIsImporting when applying the fix.packages/shared-types/src/index.ts (1)
405-435:⚠️ Potential issue | 🟠 Major로컬 경로 계약이 URL/네트워크 경로를 그대로 허용합니다.
Line 421-428과 Line 459-460은 빈 문자열만 거르기 때문에
https://...,file://...,\\\\server\\share\\...같은 비로컬 경로도 모두 통과합니다. 이후 파일 접근 로직이 이 값을 신뢰하면 로컬 분석 경계를 우회하게 됩니다.🔒 제안 수정안
+function isLocalFilesystemPath(value: unknown): value is string { + return ( + typeof value === "string" && + value.trim().length > 0 && + !/^[a-z]+:\/\//i.test(value) && + !value.startsWith("\\\\") + ); +} + /** Documented. */ function validateProjectBootstrapSummary(value: unknown): string | null { if (!isRecord(value)) { return "Invalid project bootstrap summary: invalid field 'root'"; } @@ - if (typeof value.projectRoot !== "string" || value.projectRoot.trim().length === 0) { + if (!isLocalFilesystemPath(value.projectRoot)) { return "Invalid project bootstrap summary: invalid field 'projectRoot'"; } - if (typeof value.cacheRoot !== "string" || value.cacheRoot.trim().length === 0) { + if (!isLocalFilesystemPath(value.cacheRoot)) { return "Invalid project bootstrap summary: invalid field 'cacheRoot'"; } - if (typeof value.tempRoot !== "string" || value.tempRoot.trim().length === 0) { + if (!isLocalFilesystemPath(value.tempRoot)) { return "Invalid project bootstrap summary: invalid field 'tempRoot'"; } @@ /** Documented. */ function validateLocalAudioSource(value: unknown): string | null { if (!isRecord(value)) { return "Invalid local audio source: invalid field 'root'"; } @@ - if (typeof value.sourcePath !== "string" || value.sourcePath.trim().length === 0) { + if (!isLocalFilesystemPath(value.sourcePath)) { return "Invalid local audio source: invalid field 'sourcePath'"; }As per coding guidelines "Do not add network-dependent runtime paths for local analysis" and "Treat files, URLs, metadata, model artifacts, and project files as untrusted input".
Also applies to: 449-470
apps/desktop/src/lib/analysis.ts (1)
41-46:⚠️ Potential issue | 🟠 MajorTauri 환경 감지 로직을 추가하여 브라우저 폴백을 활성화하세요.
getInvoke()은window존재 여부만 확인하므로, Tauri 브리지가 없는 일반 브라우저 환경에서도 import된invoke를 반환합니다. 이로 인해invokeAnalysis()에서browserFallback()에 절대 도달하지 못하고, 항상 Tauri 전용invoke()함수를 호출하게 됩니다.
@tauri-apps/api/core의isTauri함수를 사용하여 Tauri 런타임 여부를 확인하고, Tauri 환경이 아닐 때만 null을 반환하도록 수정하세요.수정 예시
-import { invoke } from "@tauri-apps/api/core"; +import { invoke, isTauri } from "@tauri-apps/api/core"; function getInvoke(): TauriInvoke | null { if (typeof window === "undefined") { return null; } + if (!isTauri()) { + return null; + } return window.__TAURI_INVOKE__ ?? invoke; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/lib/analysis.ts` around lines 41 - 46, getInvoke currently only checks for window and returns the imported tauri invoke in non-Tauri browsers, preventing browserFallback() in invokeAnalysis from ever running; update getInvoke to import and use isTauri from "@tauri-apps/api/core" and return null when isTauri() is false (i.e., not running under Tauri). Ensure references to getInvoke(), invokeAnalysis(), and browserFallback() are preserved so the changed getInvoke() correctly signals non-Tauri environments and lets invokeAnalysis call browserFallback().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/desktop/src-tauri/src/main.rs`:
- Around line 790-805: The code trusts the subprocess-supplied metadata.filepath
and uses it directly to access the filesystem; instead canonicalize the path and
validate it is inside your cache root before using it. In the block that reads
metadata (variables: metadata, filepath, path, metadata_fs, extension), call
Path::canonicalize (or equivalent) on the parsed filepath, resolve your cache
root to a canonical path (cache_root or the existing cache directory variable),
and check that the canonicalized filepath starts with/has_parent equal to the
canonical cache root; if the check fails, return an error (e.g., "Invalid file
path: outside cache") rather than proceeding to read metadata or use the file.
Ensure you still handle canonicalize errors and keep the existing metadata_fs
and extension extraction only after the path validation passes.
In `@apps/desktop/src/App.test.tsx`:
- Around line 73-76: Add assertions in the test that consume the expanded
fixture to verify the new contract fields are actually used: assert that
overlapWarnings (the string "Density warning: competing with Keyboard Left Hand
in low register.") appears in the rendered output or in a component prop/state
after rendering (e.g., query the DOM for the warning text or check the component
that receives the fixture), and assert that partGraph (the fixture's graph
structure) is processed by the rendering/logic by checking for a rendered
node/edge label or by spying/inspecting the function that processes partGraph
(references: the test in apps/desktop/src/App.test.tsx using the fixture, the
overlapWarnings array and the partGraph object). Ensure each assertion fails if
those fields are ignored so the test verifies real usage.
In `@apps/desktop/src/features/home/index.tsx`:
- Around line 17-40: Replace the hardcoded UI strings ("Sections", "Roles",
"Export" and the two empty-state paragraphs) with i18n lookups instead of
literals: locate the JSX that renders the card labels (the divs that show
Sections/Roles/Export using song and song.exportSummary) and the empty-state
paragraphs below them, import/use the project's translation helper (e.g.,
useTranslation/t) and render keys like home.cards.sections, home.cards.roles,
home.cards.export, home.empty.title and home.empty.subtitle (or your repo's
established keys) so all labels and the empty-state copy come from the locale
system rather than hardcoded strings.
In `@apps/desktop/src/features/settings/index.tsx`:
- Around line 12-45: The UI strings in the settings component are hardcoded
(e.g., the headings "Supported Audio Formats", "Analysis Pipeline", "About", the
list items "Decode audio source", "Draft section and role extraction", "Separate
stems by category", "Persist analysis results", and the about paragraph) causing
mixed-language rendering; replace these literals with calls to the shared
translation function t using distinct translation keys (for example
settings.supportedAudio.title, settings.analysis.pipeline.item1..item4,
settings.about.title, settings.about.description) and render t('...') in place
of each string while keeping the SUPPORTED_AUDIO_FORMATS.map usage and span
content (use t for the headings, list items, and paragraph).
In `@apps/desktop/src/features/workspace/RoleSwitcher.tsx`:
- Around line 9-10: Replace the vague JSDoc comment above the RoleSwitcher
component: remove `/** Documented. */` and add a concise JSDoc that states the
component responsibility and the meaning of its props (RoleSwitcher, props:
roles, activeRole, onRoleChange from RoleSwitcherProps) — e.g., one-line summary
of what RoleSwitcher renders, what shape/intent of roles is, what activeRole
represents, and that onRoleChange is called when the selection changes; if you
prefer, remove the JSDoc entirely rather than keeping an unhelpful placeholder.
In `@apps/desktop/src/features/workspace/SectionRoadmap.tsx`:
- Around line 137-139: The current mapping role.overlapWarnings.map((warning,
wIdx) => ...) uses the loop index wIdx as the React key which can cause
unnecessary re-renders; change the key to a stable unique identifier for each
warning (e.g., use warning.id if warnings are objects with an id, or fallback to
the warning text string if unique) in the JSX where the warning is rendered so
React can correctly track items instead of relying on wIdx.
In `@apps/desktop/src/lib/export.ts`:
- Around line 17-25: The CSV injection check currently uses /^[=+\-@]/ on value
and misses cases with leading spaces/tabs; update the detection to check for
leading whitespace (e.g. /^\s*[=+\-@]/) and when escaping (variables value and
escapedValue) preserve those leading whitespace characters instead of simply
prefixing a quote to the raw string—i.e. locate the leading whitespace, insert a
single quote immediately after it (keeping the original whitespace), then
continue with the existing quote-escaping and quoting logic.
In `@CHANGELOG.md`:
- Around line 1-17: Move the top-level "# Changelog" header to the very top of
the file (so the document starts with "# Changelog") and place "## [Unreleased]"
after it; ensure every section heading (e.g., "# Changelog", "## [Unreleased]",
"## [0.1.1] - 2026-04-28", and the subsection headings "### Added" and "###
Fixed") is followed by a single blank line, and keep a single blank line between
sections/lists so the lists under "### Added" and "### Fixed" have an empty line
above them to satisfy MD041 and MD022.
In `@docs/plans/2026-03-28-ml-engine-integration.md`:
- Around line 3-55: Add a single blank line after every Markdown heading to
satisfy MD022: insert one empty line immediately following headings like "##
Overview", "## Execution Tracks", "### Track 1: Temporal Foundation (`#105`)",
"### Track 2: Spectral & Stem Separation (`#106`)", "### Track 3: Harmonic & Pitch
Pipelines (`#107`) (COMPLETED)", "### Track 4: Structural Graph Assembly (`#108`)",
"### Track 5: Orchestration & UX (`#109`)", "## Security Notes", "### Attack
Surface", "### Trust Boundary", "### Mitigations", "### Test Points", and "###
Realistic Threats" so that each heading is followed by exactly one blank line to
eliminate the markdownlint-cli2 MD022 warnings.
In `@docs/plans/2026-04-28-pr-159-rollout.md`:
- Line 172: The markdown file docs/plans/2026-04-28-pr-159-rollout.md is missing
the required single trailing newline (MD047) at EOF; fix by ensuring the file
ends with exactly one newline character (add a single '\n' at the end), then
save so the file now concludes with one blank line to satisfy markdownlint CI.
- Around line 146-172: Expand the "Security Notes" section to explicitly
document artifact integrity verification and safe-fail behavior: add steps for
end-user and CI-side signature/hash checks (e.g., SHA256 and code-signature
validation), exact failure modes (what the app should do on signature/hash
verification failure), and where/what to log while avoiding sensitive
paths/names (privacy impact); reference and require CI/release checks per
docs/security/cross-platform-build-policy.md and include concrete test points
for verifying release signatures, automated release validation, and privacy-safe
logging behavior in the Test Points subsection.
- Line 1: Remove the stray developer debug comment bearing the "RESTORE POINT"
marker (the HTML comment that exposes a local home path) from the file and
commit, and add a cleanup step to prevent auto-inserted debug annotations:
search for and delete any HTML comment containing "RESTORE POINT" or home-dir
patterns like "~/.gstack" (the offending comment), and update the
commit/pre-commit hook or the tool that generates these notes so it no longer
emits local-path debug comments before commits.
- Around line 2-172: The markdown has many MD022/MD058 lint warnings: add a
single blank line before and after every heading (e.g., "## Problem Statement",
"### 1. Stabilize Branch", etc.) and ensure each table (e.g., "### 1. CEO DUAL
VOICES — CONSENSUS TABLE", "Error & Rescue Registry" tables) is preceded and
followed by a blank line; scan the document for all headings and table blocks
and insert the missing empty lines so heading/table spacing conforms to the
MD022/MD058 rules.
In `@docs/security/dependency-policy.md`:
- Line 105: Replace the vague "e.g." phrasing in
docs/security/dependency-policy.md with an explicit list of advisory IDs or a
clear canonical reference: read the actual ignore entries from
apps/desktop/src-tauri/.cargo/audit.toml and either paste the exact advisory IDs
(e.g. RUSTSEC-2024-0413, RUSTSEC-2024-0429, RUSTSEC-2025-0057, etc.) into the
paragraph or change the sentence to point readers to
apps/desktop/src-tauri/.cargo/audit.toml as the canonical source for the full
advisory ID list; ensure the text matches the "exact advisory ID" principle and
remove "e.g." so the exception is unambiguous.
In `@packages/shared-types/src/index.ts`:
- Around line 853-885: validatePartGraphNode currently only checks shape but not
that role_id exists in the section, that handoff targets reference existing
role_ids, or that there are duplicate nodes; update validatePartGraphNode to (1)
accept a lookup/set of valid role ids from the section (or call a helper like
getSectionRoleIds) and verify value.role_id is one of them, (2) verify every
entry in value.handoff_to and value.handoff_from exists in that same role-id
set, and (3) detect duplicate role_id entries across the graph (or expose a
separate validatePartGraph function that iterates nodes and checks duplicates)
so that role existence, handoff references, and duplicate nodes are rejected
rather than only shape-validated. Ensure you update callers to pass the section
role-id set to validatePartGraphNode or use the new graph-level validator that
references validatePartGraphNode.
In `@scripts/fix-version-format.sh`:
- Around line 1-11: Add strict shell modes to fail fast by enabling "set -euo
pipefail" (and optionally setting IFS=$'\n\t') immediately after the shebang;
this ensures any failure in commands that compute CURRENT_VERSION, the
grep/printf check, cut, or the echo write to VERSION_FILE will abort the script.
Keep the existing variable names (VERSION_FILE, CURRENT_VERSION, NEW_VERSION)
and logic but run them under the strict mode so errors are not silently ignored.
In `@services/analysis-engine/src/bandscope_analysis/chords/analyzer.py`:
- Around line 67-78: The loop over section_roles in analyzer.py must validate
inputs and normalize the harmony.source: ensure each role is a dict before
accessing role.get("harmony"), ensure harmony is a dict before using
harmony["chord"], and skip non-dict roles to avoid exceptions; when building the
chord entry (where seen_chords, chords and chord_name are used) validate
harmony.get("source") against the allowed values ("model", "user") and normalize
anything else to "model" (or a safe default), and also coerce functionLabel to a
string via str(harmony.get("functionLabel", "")) as already done so the returned
ChordLabel contract is preserved.
In `@services/analysis-engine/src/bandscope_analysis/cli.py`:
- Around line 79-85: The code calls request["localSource"].get("sourcePath")
without verifying that request["localSource"] is a dict, risking AttributeError;
update the conditional to check that request.get("localSource") is a dict (e.g.,
isinstance(request.get("localSource"), dict)) before calling .get, and then read
sourcePath into audio_path only if that dict check passes (refer to the
variables request, localSource, and audio_path in the existing block).
In `@services/analysis-engine/src/bandscope_analysis/ranges/analyzer.py`:
- Around line 201-211: The loop over section_roles assumes every item is a dict
and will raise if a role is a string or None; update the loop in analyzer.py to
validate each role before using role.get: skip non-dict roles (and optionally
log a warning including the offending value and the containing section id/name)
and only extract role_id/role_name/lowestNote/highestNote when isinstance(role,
dict) and role_range is a dict; this preserves existing behavior for malformed
sections (like the surrounding method does) and prevents one bad role from
aborting the whole section analysis.
- Around line 58-67: The parser currently treats a '-' as part of the octave
only when it is the last character, causing "C-1" to be split as ("C-", "1") and
mis-parsed in _note_to_midi(); update the reverse-scan logic in the loop that
examines variable note so that a '-' is considered part of the octave when it is
directly followed by digits (e.g., change the char check to allow note[i] == '-'
when i < len(note)-1 and note[i+1].isdigit()), and also tighten the octave_str
validation to accept a leading '-' followed by digits (e.g., check
octave_str.isdigit() or (octave_str.startswith('-') and
octave_str[1:].isdigit())); this ensures negative octaves like "C-1" produce
("C", -1) for _note_to_midi().
In `@services/analysis-engine/src/bandscope_analysis/roles/extractor.py`:
- Around line 65-79: The pitch-tracking block in extractor.py overwrites
existing default vocal_range and bass_range with empty strings when
pitch_tracker.track returns None or incomplete results; update the logic in the
extractor role so that after calling pitch_tracker.track(...) you only assign
vocal_range or bass_range if p_res is truthy and both p_res["lowest_note"] and
p_res["highest_note"] (or p_res.get("lowest_note")/get("highest_note")) are
present/non-empty — otherwise leave the existing default range intact; target
the pitch_tracker.track calls and the vocal_range/bass_range assignments to add
these presence checks before updating.
In `@services/analysis-engine/src/bandscope_analysis/separation/model.py`:
- Line 24: StemDescriptor.category is currently typed as str which can break the
category contract; change its type annotation to use the existing StemCategory
enum (StemCategory) so only valid enum values are allowed, update any imports or
forward-references in model.py to reference StemCategory, and adjust any places
that construct or serialize StemDescriptor (e.g., constructors,
from_dict/to_dict or dataclass usages) to convert between strings and
StemCategory where needed.
In `@services/analysis-engine/tests/test_chord_recognizer.py`:
- Around line 142-144: The test is too strict about chord label formatting:
change the assertions that reference identified_chords (computed from result) to
accept both short and verbose labels (e.g., "C" and "C:maj"); implement this by
replacing direct equality checks with existence checks that match labels
starting with "C" and "G" (e.g., any(ch.startswith("C") for ch in
identified_chords) and any(ch.startswith("G") for ch in identified_chords)) so
the test passes for either "C"/"C:maj" and "G"/"G:maj".
- Line 24: Remove the leftover debug print statement in the test (the
print("RESULT:", result) in test_chord_recognizer.py) to avoid CI log noise;
locate the print in the test function that produces `result` and delete it (or
replace it with an assertion or logger.debug if you need to keep the output for
local debugging), ensuring the test only uses assertions to validate `result`.
In `@services/analysis-engine/tests/test_release_packaging.py`:
- Around line 59-74: The test calls a missing function find_installer_packages
from scripts/release/package_desktop_artifact.py, causing AttributeError; add an
implementation named find_installer_packages in that module (or export it if
implemented elsewhere) that accepts a Path base_dir and returns a list of
installer Paths (e.g., scanning BANDSCOPE_TARGET_TRIPLE subdirs for
.dmg/.pkg/.zip as the test expects), and ensure the function name and signature
match the test (find_installer_packages(tmp_path)); update any module-level
exports if necessary so the test’s load_module call can access it.
- Line 23: The test calls to artifact_identity(...) fail because the production
function artifact_identity is defined with no parameters; update
artifact_identity in scripts/release/package_desktop_artifact.py to accept a
filename (e.g., def artifact_identity(filename: str)) and compute the identity
from that input, preserving existing behavior when callers pass a path or
basename; then update any internal call sites to pass through the filename or to
call artifact_identity() with no arg only if intended, and ensure tests that
pass a filename continue to work with the new signature.
---
Outside diff comments:
In `@apps/desktop/src/App.tsx`:
- Around line 126-132: handleImportYoutube currently passes raw youtubeUrl down
to importYoutubeUrl/IPC; trim and validate it first: call const raw =
youtubeUrl?.trim() and if empty setSelectionError and return; then try to
construct new URL(raw) and ensure url.protocol is "http:" or "https:" (otherwise
setSelectionError and return). Only after these guards call importYoutubeUrl
with the validated URL string; keep existing setIsImporting/setSelectionError
flows and reference handleImportYoutube, importYoutubeUrl, youtubeUrl,
setSelectionError, and setIsImporting when applying the fix.
In `@apps/desktop/src/lib/analysis.ts`:
- Around line 41-46: getInvoke currently only checks for window and returns the
imported tauri invoke in non-Tauri browsers, preventing browserFallback() in
invokeAnalysis from ever running; update getInvoke to import and use isTauri
from "@tauri-apps/api/core" and return null when isTauri() is false (i.e., not
running under Tauri). Ensure references to getInvoke(), invokeAnalysis(), and
browserFallback() are preserved so the changed getInvoke() correctly signals
non-Tauri environments and lets invokeAnalysis call browserFallback().
In `@services/analysis-engine/tests/test_release_packaging.py`:
- Around line 111-149: The test
test_release_packaging_main_writes_arch_specific_manifest sets up only a DMG
artifact but the implemented packaging.main() currently requires other artifacts
(binary/frontend dist/metadata) and emits .zip + .manifest.txt names, so update
packaging.main() (in package_desktop_artifact_main) to accept the DMG-only case
and produce an architecture-specific .dmg.manifest.txt when
BANDSCOPE_ARTIFACT_OS== "macos" and BANDSCOPE_ARTIFACT_ARCH=="arm64": detect the
target triple/env vars, look for the .dmg under the same target bundle path
(aarch64-apple-darwin/.../bundle/dmg/App.dmg), skip or make optional the checks
for other dist files when a .dmg exists, and write the manifest file named
bandscope-macos-arm64-<GITHUB_SHA_PREFIX>.dmg.manifest.txt with platform and
arch lines so the test's expected manifest path and contents are produced.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: fa83d1c4-b487-4d88-b975-55e6643eb61e
⛔ Files ignored due to path filters (3)
apps/desktop/src-tauri/Cargo.lockis excluded by!**/*.lockpackage-lock.jsonis excluded by!**/package-lock.jsonservices/analysis-engine/uv.lockis excluded by!**/*.lock
📒 Files selected for processing (78)
.github/workflows/bandit.yml.github/workflows/build-baseline.yml.github/workflows/ci.yml.github/workflows/codeql.yml.github/workflows/dependency-review.yml.github/workflows/ossf-scorecard.yml.github/workflows/sbom.yml.github/workflows/security-audit.yml.github/workflows/trivy.yml.gitignoreCHANGELOG.mdREADME.mdSECURITY.mdVERSIONapps/desktop/src-tauri/.cargo/audit.tomlapps/desktop/src-tauri/src/main.rsapps/desktop/src/App.test.tsxapps/desktop/src/App.tsxapps/desktop/src/features/chords/index.tsxapps/desktop/src/features/home/index.tsxapps/desktop/src/features/player/index.tsxapps/desktop/src/features/ranges/index.tsxapps/desktop/src/features/settings/index.tsxapps/desktop/src/features/workspace/ConfidenceBadge.tsxapps/desktop/src/features/workspace/RoleSwitcher.tsxapps/desktop/src/features/workspace/SectionRoadmap.tsxapps/desktop/src/features/workspace/Workspace.tsxapps/desktop/src/features/workspace/WorkspaceStates.tsxapps/desktop/src/i18n/index.tsapps/desktop/src/lib/analysis.tsapps/desktop/src/lib/export.test.tsapps/desktop/src/lib/export.tsdocs/plans/2026-03-28-ml-engine-integration.mddocs/plans/2026-04-28-pr-159-rollout.mddocs/security/dependency-policy.mdeslint.config.jspackage.jsonpackages/shared-types/src/index.tspackages/shared-types/test/index.test.tsscripts/checks/security_gates.pyscripts/checks/verify_docs.pyscripts/checks/verify_github_bootstrap_policy.pyscripts/checks/verify_security_notes.pyscripts/checks/verify_supply_chain.pyscripts/fix-version-format.shscripts/release/package_desktop_artifact.pyservices/analysis-engine/pyproject.tomlservices/analysis-engine/src/bandscope_analysis/chords/__init__.pyservices/analysis-engine/src/bandscope_analysis/chords/analyzer.pyservices/analysis-engine/src/bandscope_analysis/chords/chord_recognizer.pyservices/analysis-engine/src/bandscope_analysis/chords/model.pyservices/analysis-engine/src/bandscope_analysis/cli.pyservices/analysis-engine/src/bandscope_analysis/ranges/__init__.pyservices/analysis-engine/src/bandscope_analysis/ranges/analyzer.pyservices/analysis-engine/src/bandscope_analysis/ranges/model.pyservices/analysis-engine/src/bandscope_analysis/ranges/pitch_tracker.pyservices/analysis-engine/src/bandscope_analysis/roles/extractor.pyservices/analysis-engine/src/bandscope_analysis/separation/__init__.pyservices/analysis-engine/src/bandscope_analysis/separation/model.pyservices/analysis-engine/src/bandscope_analysis/separation/separator.pyservices/analysis-engine/src/bandscope_analysis/temporal/__init__.pyservices/analysis-engine/src/bandscope_analysis/temporal/analyzer.pyservices/analysis-engine/src/bandscope_analysis/temporal/model.pyservices/analysis-engine/src/bandscope_analysis/youtube.pyservices/analysis-engine/tests/test_chord_recognizer.pyservices/analysis-engine/tests/test_chords.pyservices/analysis-engine/tests/test_cli.pyservices/analysis-engine/tests/test_pitch_tracker.pyservices/analysis-engine/tests/test_priority.pyservices/analysis-engine/tests/test_ranges.pyservices/analysis-engine/tests/test_release_packaging.pyservices/analysis-engine/tests/test_roles_ml.pyservices/analysis-engine/tests/test_sections.pyservices/analysis-engine/tests/test_separation.pyservices/analysis-engine/tests/test_supply_chain_policy.pyservices/analysis-engine/tests/test_temporal.pyservices/analysis-engine/tests/test_tuning.pyservices/analysis-engine/tests/test_youtube.py
💤 Files with no reviewable changes (3)
- scripts/checks/verify_docs.py
- scripts/checks/verify_github_bootstrap_policy.py
- scripts/checks/verify_security_notes.py
✅ Actions performedComments resolved and changes approved. |
Fixes test failures caused by the change from zip packaging to DMG/EXE installer packaging.