projectops 4.28.1 → 4.28.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/cli/args.js +3 -2
- package/src/core/assets.js +4 -0
- package/src/core/detect-fs.js +6 -1
package/README.md
CHANGED
package/package.json
CHANGED
package/src/cli/args.js
CHANGED
|
@@ -7,7 +7,8 @@ export const DEPLOY_TARGETS = ["docker-ssh", "vercel", "none"];
|
|
|
7
7
|
export const PUBLISH_TARGETS = ["nexus", "npm", "github-packages"];
|
|
8
8
|
export const INTENT_VALUES = ["app", "library", "both", "none", "manual"];
|
|
9
9
|
const SEMVER_RE = /^\d+\.\d+\.\d+$/;
|
|
10
|
-
|
|
10
|
+
// 유니코드 글자·숫자 허용 (#719) — 공백·셸 메타문자는 문자 클래스에 없어 그대로 거부된다.
|
|
11
|
+
const BRANCH_RE = /^[\p{L}\p{N}][\p{L}\p{N}._/-]*$/u;
|
|
11
12
|
// 허용 실행 모드 (#665) — 오타가 조용히 "복사 0건 성공"으로 끝나지 않게 한다.
|
|
12
13
|
export const MODE_VALUES = ["full", "version", "workflows", "issues", "skills", "doctor", "interactive"];
|
|
13
14
|
|
|
@@ -103,7 +104,7 @@ export function parseArgs(argv) {
|
|
|
103
104
|
const v = (args.shift() ?? "").trim();
|
|
104
105
|
// 워크플로우 yaml·셸에 그대로 삽입되므로 안전한 브랜치명만 허용 (#676)
|
|
105
106
|
if (v && (!BRANCH_RE.test(v) || v.includes("..") || v.endsWith("/") || v.endsWith(".lock"))) {
|
|
106
|
-
throw new CliError(`--deploy-branch 값은
|
|
107
|
+
throw new CliError(`--deploy-branch 값은 글자·숫자·. _ - / 로 이루어진 브랜치명이어야 합니다: '${v}'`);
|
|
107
108
|
}
|
|
108
109
|
if (v) result.deployBranch = v;
|
|
109
110
|
break;
|
package/src/core/assets.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// 템플릿 자산 획득 + 제외 적용 (.sh download_template 등가) — template_integrator.sh 2064~2141.
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { mkdirSync } from "node:fs";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { exists, readText, copyDirSync, remove } from "./fsutil.js";
|
|
5
6
|
import { DOCS_TO_REMOVE, PLUGIN_ITEMS_TO_REMOVE } from "./exclusions.js";
|
|
@@ -21,6 +22,9 @@ export function acquireTemplate({ tempDir, source = { type: "git" } }) {
|
|
|
21
22
|
copyDirSync(source.path, tempDir);
|
|
22
23
|
} else {
|
|
23
24
|
const repo = source.repo || TEMPLATE_REPO;
|
|
25
|
+
// clone 은 stdio 를 버려 실패 원인이 사라진다 — 폴더가 읽기 전용이어도 "내려받지 못했다"로 오도되므로
|
|
26
|
+
// 먼저 만들어 권한 오류(EACCES/EPERM/EROFS)를 그대로 올린다 (#720). 빈 폴더에는 clone 이 가능하다.
|
|
27
|
+
mkdirSync(tempDir, { recursive: true });
|
|
24
28
|
execFileSync("git", ["clone", "--depth", "1", "--quiet", repo, tempDir], { stdio: "ignore" });
|
|
25
29
|
}
|
|
26
30
|
applyExclusions(tempDir);
|
package/src/core/detect-fs.js
CHANGED
|
@@ -4,7 +4,8 @@ import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
|
4
4
|
import { join, basename } from "node:path";
|
|
5
5
|
import { execFileSync } from "node:child_process";
|
|
6
6
|
import { detectTypesFromMarkers, detectVersionFromFiles, suggestTypesByExtScan } from "./detect.js";
|
|
7
|
-
import { parseExisting } from "./version-yml.js";
|
|
7
|
+
import { parseExisting, convertLegacySingularType } from "./version-yml.js";
|
|
8
|
+
import { VALID_TYPES } from "../context.js";
|
|
8
9
|
|
|
9
10
|
const hasFile = (root) => (rel) => existsSync(join(root, rel));
|
|
10
11
|
const readFile = (root) => (rel) => {
|
|
@@ -50,6 +51,10 @@ export function detectTypes(root) {
|
|
|
50
51
|
if (existsSync(vy)) {
|
|
51
52
|
const { types } = parseExisting(readFileSync(vy, "utf8"));
|
|
52
53
|
if (types.length) return types; // basic 포함, 명시돼 있으면 그대로
|
|
54
|
+
// v4.1.0 이전 단수 project_type 키 (#718) — 마커가 없어도 명시된 값을 복원한다.
|
|
55
|
+
// 안 그러면 마커 없는 저장소가 basic 으로 떨어져 기존 타입의 워크플로우가 고아가 된다.
|
|
56
|
+
const legacy = (convertLegacySingularType(readFileSync(vy, "utf8")) || "").match(/^project_types: \["([a-z-]+)"\]/m);
|
|
57
|
+
if (legacy && VALID_TYPES.includes(legacy[1])) return [legacy[1]];
|
|
53
58
|
}
|
|
54
59
|
const byMarkers = detectTypesFromMarkers({ has: hasFile(root), read: readFile(root) });
|
|
55
60
|
if (byMarkers.length === 1 && byMarkers[0] === "basic") {
|