diff --git a/VERSION b/VERSION index 0b2eb36..c1e43e6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.7.2 +3.7.3 diff --git a/install.sh b/install.sh index acca556..e81352a 100755 --- a/install.sh +++ b/install.sh @@ -25,7 +25,7 @@ from urllib.parse import urljoin from urllib.request import Request, urlopen -VERSION = "3.7.2" +VERSION = "3.7.3" REPOSITORY = "https://raw.githubusercontent.com/kimdzhekhon/Universal-Build-Script" RELEASE_REF = os.environ.get("UBS_INSTALL_REF", f"v{VERSION}") BASE_URL = os.environ.get("UBS_INSTALL_BASE_URL", f"{REPOSITORY}/{RELEASE_REF}").rstrip("/") + "/" diff --git a/scripts/ubs.py b/scripts/ubs.py index ad426ee..a9e0e74 100755 --- a/scripts/ubs.py +++ b/scripts/ubs.py @@ -1239,17 +1239,17 @@ def pattern_static_prefix(pattern: str) -> Optional[str]: def preferred_output_roots(project: Project, artifacts: Sequence[Path]) -> List[Path]: - """Derive common output roots per project type straight from ARTIFACT_PATTERNS. + """Derive output roots per project type straight from ARTIFACT_PATTERNS. Only prefixes that actually produced an artifact this build are considered, so a single-output build (e.g. just an .aab) opens its own specific folder - instead of the noisy shared "build" root. Prefixes sharing the same - top-level path segment are collapsed to their common ancestor only when - more than one of them has real output (e.g. flutter producing both an - .aab and build/web), while prefixes under different top-level segments - stay separate (e.g. tauri's "src-tauri/..." and "signing/build"). + instead of the noisy shared "build" root. Two prefixes are only merged + when one is an ancestor of the other (nesting) — separate output types + that merely share a top-level segment (e.g. flutter's aab under + build/app/outputs/... and ipa under build/ios/ipa) stay as distinct + folders instead of collapsing to that shared segment. """ - groups: Dict[str, List[str]] = {} + resolved_prefixes: List[Path] = [] for pattern in ARTIFACT_PATTERNS.get(project.type, []): prefix = pattern_static_prefix(pattern) if not prefix: @@ -1257,8 +1257,22 @@ def preferred_output_roots(project: Project, artifacts: Sequence[Path]) -> List[ resolved = (project.path / prefix).resolve() if not any(artifact == resolved or resolved in artifact.parents for artifact in artifacts): continue - groups.setdefault(prefix.split("/", 1)[0], []).append(prefix) - return [project.path / os.path.commonpath(prefixes) for prefixes in groups.values()] + resolved_prefixes.append(resolved) + + roots: List[Path] = [] + for resolved in resolved_prefixes: + merged = False + for index, existing in enumerate(roots): + if existing == resolved or existing in resolved.parents: + merged = True + break + if resolved in existing.parents: + roots[index] = resolved + merged = True + break + if not merged: + roots.append(resolved) + return roots def artifact_output_directories(project: Project) -> List[Path]: diff --git a/scripts/update-manifest.txt b/scripts/update-manifest.txt index 9cea6cf..dcae889 100644 --- a/scripts/update-manifest.txt +++ b/scripts/update-manifest.txt @@ -1,9 +1,9 @@ # scripts/generate-update-manifest.sh로 생성합니다. 임의 편집하지 마세요. -version 3.7.2 -file c6985d515b3473f1ea6ec6306d74ea3cb913b64740172689a8e2b1edde3ec9fc VERSION +version 3.7.3 +file c5c590b00cd6c1d7a69736ea08aa29cdd07d75eae430122c5b6651d299368c49 VERSION file 62d7189d00ccadbdeae9647a37b80db6ed9e179bfcf5b2f1d4d1c487dbc815bf build.sh -file 707238d61ab00e3531fd71e957231868a9518085e989286788e0deb49e875b9c install.sh -file 520c92fc76c608368a8b474bca95c46875699981e4d61d579aa7daa80faaa828 scripts/ubs.py +file ff3cddb9c631c23b1904a81bf363b9ff01fd373ff968a846aa4a4592b52b9b84 install.sh +file a82c63e4116bac963d6745cf8e17dade5d95f4f7af543d481933cc5cc3e70129 scripts/ubs.py file df0231e3cc0e584be7ae3ade3f1c0a7f92afb2124ec8a15bdb51c76737bbe1e0 scripts/ubs_mcp.py file 0a3b9d28fbe62bc55c073f5337954ae92ffca7482fca5d1f681dc99333363416 scripts/bootstrap-update.sh file 7b9a21a0854e0ca0476ae6ee38f2b7fc552446c97448ee655995f91e5c6f23d5 scripts/build-rust-helper.sh diff --git a/tests/test-update.sh b/tests/test-update.sh index 54e55ec..9367ccb 100755 --- a/tests/test-update.sh +++ b/tests/test-update.sh @@ -146,8 +146,8 @@ assert result["schema_version"] == 1 assert result["ok"] is True assert result["mode"] == "check" assert result["status"] == 0 -assert result["local_version"] == "3.7.2" -assert result["remote_version"] == "3.7.2" +assert result["local_version"] == "3.7.3" +assert result["remote_version"] == "3.7.3" assert result["changed_paths"] == [] assert result["backup_path"] is None assert isinstance(result["output"], list) @@ -196,7 +196,7 @@ fi } # 원격 버전이 더 낮으면 명시적 허용 없이 적용하지 않아야 한다. -sed 's/^version 3\.7\.2$/version 2.0.0/' "$REPO_DIR/scripts/update-manifest.txt" \ +sed 's/^version 3\.7\.3$/version 2.0.0/' "$REPO_DIR/scripts/update-manifest.txt" \ > "$REMOTE/scripts/update-manifest.txt" if UBS_UPDATE_BASE_URL="file://$REMOTE" UBS_UPDATE_ALLOW_FILE=true \ bash "$TARGET/build.sh" update --check >/dev/null 2>&1; then diff --git a/tests/test_python_core.py b/tests/test_python_core.py index a564054..3a743a5 100644 --- a/tests/test_python_core.py +++ b/tests/test_python_core.py @@ -33,17 +33,24 @@ def test_standard_streams_are_configured_for_utf8(self) -> None: encoding="utf-8", errors="backslashreplace", ) - def test_flutter_artifacts_open_the_common_build_root(self) -> None: + def test_flutter_multiple_outputs_open_their_own_folders_not_shared_build_root(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary).resolve() - output = root / "build/app/outputs/bundle/release" - output.mkdir(parents=True) - (output / "app-release.aab").write_bytes(b"bundle") + aab_output = root / "build/app/outputs/bundle/release" + aab_output.mkdir(parents=True) + (aab_output / "app-release.aab").write_bytes(b"bundle") + ipa_output = root / "build/ios/ipa" + ipa_output.mkdir(parents=True) + (ipa_output / "app.ipa").write_bytes(b"ipa") web = root / "build/web" web.mkdir(parents=True) + # Each output type gets its own folder — they must not collapse to + # the shared "build" segment, which would drag in unrelated + # plugin build caches that live under build/ regardless of which + # outputs were actually produced. self.assertEqual( ubs.artifact_output_directories(ubs.Project("flutter", root)), - [root / "build"], + sorted([aab_output, ipa_output, web], key=str), ) def test_flutter_single_output_opens_its_own_folder_not_whole_build(self) -> None: