릴리스 자산
CLI 도구, 데스크톱 애플리케이션, 또는 네이티브 라이브러리를 publish할 때는 플랫폼별 바이너리, 설치 파일, WASM 모듈, 네이티브 바인딩 같은 컴파일 결과물을 GitHub Release에 함께 첨부해야 하는 경우가 많습니다. pubm은 이를 releaseAssets 설정 필드로 처리합니다.
언제 release asset이 필요한가
섹션 제목: “언제 release asset이 필요한가”다음 경우에 releaseAssets를 설정합니다.
- CLI 바이너리를 배포하고 GitHub Releases에서 내려받을 수 있게 하고 싶을 때
- 데스크톱 앱(
dmg,msi)을 만들고 릴리스마다 설치 파일을 넣고 싶을 때 - 런타임에 사용자가 내려받는 WASM 모듈을 컴파일할 때
- 여러 플랫폼용 네이티브 바인딩을 만들 때
- 산출물과 함께 checksum도 두고 싶을 때
레지스트리(npm, jsr, crates.io)에만 publish한다면 releaseAssets는 필요하지 않습니다.
기본 설정
섹션 제목: “기본 설정”가장 단순한 형태는 glob 문자열입니다. pubm은 일치하는 파일을 찾아 경로에서 플랫폼을 감지하고, OS-aware 기본값으로 압축한 뒤 GitHub Release에 업로드합니다.
import { defineConfig } from "@pubm/core";
export default defineConfig({ releaseAssets: [ "platforms/*/bin/pubm", ],});예를 들어 platforms/darwin-arm64/bin/pubm 같은 경로가 있으면, pubm은 os: "darwin", arch: "arm64"를 감지하고, 바이너리를 pubm-darwin-arm64.tar.gz로 압축한 뒤 릴리스에 첨부합니다.
전체 설정
섹션 제목: “전체 설정”releaseAssets의 각 항목은 파일, 압축, 이름을 더 명시적으로 제어하는 객체일 수도 있습니다.
import { defineConfig } from "@pubm/core";
export default defineConfig({ // 전역 기본값: Windows는 zip, 그 외는 tar.gz compress: { windows: "zip" },
releaseAssets: [ { // 모노레포: 특정 패키지의 GitHub Release에 자산을 연결 packagePath: "packages/cli",
files: [ // 문자열: glob, 그룹 및 전역 설정을 상속 "platforms/*/bin/pubm",
// 객체: 파일 또는 패턴별로 명시적 설정 { path: "dist/*.dmg", compress: false, // .dmg 파일은 압축하지 않음 name: "myapp-{version}-{arch}", }, { path: "target/{arch}-{vendor}-{os}/release/myapp", compress: { linux: "tar.xz" }, // Linux에만 덮어쓰기 name: "myapp-{version}-{arch}-{os}", }, ],
// 그룹 기본값(전역값을 덮어쓰고, 파일 수준에 의해 다시 덮어써짐) compress: "tar.gz", name: "{name}-{platform}", }, ],});압축 우선순위
섹션 제목: “압축 우선순위”압축 형식은 높은 우선순위에서 낮은 우선순위 순으로 네 단계를 거쳐 결정됩니다.
| 단계 | 예시 |
|---|---|
파일 수준 compress | compress: false |
그룹 수준 compress | compress: "tar.gz" |
전역 compress (최상위 PubmConfig.compress) | compress: { windows: "zip" } |
| OS-aware 자동 감지 | Windows는 zip, 그 외는 tar.gz |
정의된 값이 처음 나타나는 단계가 승리합니다(file ?? group ?? global 방식). 승리한 값이 Record<string, CompressFormat>(OS 키 맵)이라면, pubm은 감지된 OS를 조회합니다. 맵에 OS가 없으면 다음 cascade 단계로 가지 않고 자동 감지로 떨어집니다.
알려진 형식은 다시 압축하지 않습니다. 명시적인 compress 설정이 없을 때 pubm은 파일 확장자를 확인합니다. 알려진 아카이브 또는 설치 파일 형식(.tar.gz, .tgz, .tar.xz, .tar.zst, .tar.bz2, .zip, .7z, .dmg, .msi, .exe, .deb, .rpm, .AppImage, .pkg, .snap, .flatpak, .wasm)과 일치하면 compress가 자동으로 false가 됩니다.
OS-aware 기본값
섹션 제목: “OS-aware 기본값”명시적인 compress 설정이 없을 때:
| 감지된 OS | 기본 형식 |
|---|---|
windows | zip |
| 그 외 모든 OS | tar.gz |
이름 템플릿 변수
섹션 제목: “이름 템플릿 변수”name 필드(또는 생성된 기본 이름)는 확장자가 없는 템플릿 문자열입니다. 확장자는 해석된 compress 값에 따라 자동으로 붙습니다.
| 변수 | 출처 | 예시 |
|---|---|---|
{name} | package.json의 이름, scope 제거 | pubm |
{version} | 릴리스 버전 | 0.4.0 |
{platform} | 캡처된 원시 문자열 또는 {os}-{arch} | darwin-arm64 |
{os} | 경로에서 파싱 | darwin |
{arch} | 경로에서 파싱 | arm64 |
{vendor} | 경로에서 파싱, 있으면 사용 | apple |
{abi} | 경로에서 파싱, 있으면 사용 | musl |
{variant} | 경로에서 파싱, 있으면 사용 | baseline |
{filename} | 확장자를 뺀 원본 파일명 | pubm |
name을 지정하지 않으면 pubm은 다음을 사용합니다.
- 플랫폼 정보가 감지되면
{filename}-{platform} - 그렇지 않으면
{filename}
확장자 규칙
섹션 제목: “확장자 규칙”name 템플릿에는 확장자를 넣지 않습니다. pubm이 compress에 따라 확장자를 붙입니다.
compress | 추가되는 확장자 |
|---|---|
"tar.gz" | .tar.gz |
"zip" | .zip |
"tar.xz" | .tar.xz |
"tar.zst" | .tar.zst |
false | 원본 파일 확장자 유지 |
경로의 capture 변수
섹션 제목: “경로의 capture 변수”path segment 자동 감지에 의존하는 대신, path 패턴에 capture 변수를 직접 넣을 수도 있습니다.
// 명시적 capture - arch와 os를 직접 추출{ path: "target/{arch}-{vendor}-{os}/release/mytool" }
// {platform} 전체를 하나의 토큰으로 capture{ path: "releases/{platform}/mytool" }capture 변수가 있으면 pubm은 각 경로 segment를 플랫폼 테이블과 대조하는 대신 그 값을 직접 사용합니다. 전체 파싱 알고리즘은 Platform Detection에서 확인합니다.
Homebrew로 publish하는 CLI 바이너리
섹션 제목: “Homebrew로 publish하는 CLI 바이너리”import { defineConfig } from "@pubm/core";import { brewTap } from "@pubm/plugin-brew";
export default defineConfig({ releaseAssets: [ "platforms/*/bin/mytool", ], plugins: [ brewTap({ formula: "Formula/mytool.rb" }), ],});brew 플러그인은 각 asset의 구조화된 ParsedPlatform을 읽어 formula 플랫폼 항목과 자동으로 매칭합니다.
설치 파일이 포함된 데스크톱 앱
섹션 제목: “설치 파일이 포함된 데스크톱 앱”export default defineConfig({ releaseAssets: [ { files: [ { path: "dist/MyApp-*.dmg", compress: false }, { path: "dist/MyApp-*.msi", compress: false }, { path: "dist/MyApp-*-linux.AppImage", compress: false }, ], name: "MyApp-{version}-{os}", }, ],});Rust 크로스 컴파일 바이너리
섹션 제목: “Rust 크로스 컴파일 바이너리”export default defineConfig({ releaseAssets: [ { files: [ { path: "target/{arch}-{vendor}-{os}-{abi}/release/mytool", name: "mytool-{version}-{os}-{arch}-{abi}", }, ], }, ],});WASM 모듈
섹션 제목: “WASM 모듈”export default defineConfig({ releaseAssets: [ { files: [ { path: "dist/mytool.wasm", compress: false }, ], }, ],});WASM 파일은 알려진 형식 목록에 들어 있으므로, 명시적 override가 없어도 compress: false가 자동으로 적용됩니다.
여러 패키지가 있는 모노레포
섹션 제목: “여러 패키지가 있는 모노레포”export default defineConfig({ releaseAssets: [ { packagePath: "packages/cli", files: ["platforms/*/bin/pubm"], }, { packagePath: "packages/native", files: ["build/Release/*.node"], compress: false, }, ],});다음 단계
섹션 제목: “다음 단계”- 전체 OS, 아키텍처, ABI, variant 테이블은 Platform Detection에서 확인합니다.
- 파이프라인의 각 단계를 가로채고 커스터마이즈하려면 Asset Pipeline Hooks를 읽습니다.
- brew 플러그인이
ParsedPlatform을 어떻게 formula 매칭에 사용하는지 보려면 Official Plugins를 읽습니다.