mirror of
https://gitee.com/pnoker/iot-dc3.git
synced 2026-09-01 15:33:10 +08:00
build: add compose shortcut targets and drop commit-msg lint hook
Generate <op>-<stack>[-<registry>] compose shortcuts and test/coverage targets in the Makefile, remove the install-hooks target and the .githooks commit-msg linter, and document the design.
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright 2016-present the IoT DC3 original author or authors.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
dc3/bin/commit_msg_lint.py "$1"
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
SHELL := /bin/bash
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
.PHONY: help env init-env clean package \
|
||||
.PHONY: help env init-env clean package test test-it test-e2e coverage deploy \
|
||||
build up stop down ps logs config pull restart refresh reset \
|
||||
dev-db dev-optional run changelog openapi install-hooks tag
|
||||
run changelog openapi tag
|
||||
|
||||
ENV_FILE ?= $(firstword $(wildcard .env) .env.example)
|
||||
RUNTIME_ENV_FILE ?= dc3/env/dev.env
|
||||
@@ -63,7 +63,9 @@ RUN_MODULE := $(RUN_MODULE_$(RUN_SERVICE))
|
||||
|
||||
MVN_SETTINGS ?= .mvn/settings.xml
|
||||
MVN_SETTINGS_ARG := $(if $(strip $(MVN_SETTINGS)),-s $(MVN_SETTINGS),)
|
||||
MVN_SUB_SETTINGS_ARG := $(if $(strip $(MVN_SETTINGS)),-s ../$(MVN_SETTINGS),)
|
||||
MVN := mvn $(MVN_SETTINGS_ARG)
|
||||
MVN_SUB := mvn $(MVN_SUB_SETTINGS_ARG)
|
||||
|
||||
CHANGE_FILE ?= dc3/doc/CHANGE.md
|
||||
FROM ?=
|
||||
@@ -101,8 +103,11 @@ help:
|
||||
@printf '%s\n' ''
|
||||
@printf '%s\n' 'Common:'
|
||||
@printf ' %-24s %s\n' 'make package' 'Build all Maven modules'
|
||||
@printf ' %-24s %s\n' 'make test' 'Run unit tests'
|
||||
@printf ' %-24s %s\n' 'make test-it' 'Run integration-test phase'
|
||||
@printf ' %-24s %s\n' 'make test-e2e' 'Run E2E harness'
|
||||
@printf ' %-24s %s\n' 'make coverage' 'Generate aggregated JaCoCo coverage'
|
||||
@printf ' %-24s %s\n' 'make run SERVICE=auth' 'Run one Spring Boot service with env auto-loaded'
|
||||
@printf ' %-24s %s\n' 'make install-hooks' 'Enable .githooks commit-msg lint'
|
||||
@printf '%s\n' ''
|
||||
@printf '%s\n' 'Compose:'
|
||||
@printf ' %-24s %s\n' 'make build' 'Build STACK images, optional SERVICES="data gateway" or GROUP=core'
|
||||
@@ -113,6 +118,12 @@ help:
|
||||
@printf ' %-24s %s\n' 'make logs' 'Follow STACK logs'
|
||||
@printf ' %-24s %s\n' 'make config' 'Render compose configuration'
|
||||
@printf '%s\n' ''
|
||||
@printf '%s\n' 'Shortcuts (auto-generated, no env vars needed):'
|
||||
@printf ' %-32s %s\n' 'make <op>-<stack>[-<registry>]' 'e.g. make up-db-cn, make logs-dev, make down-app'
|
||||
@printf ' %-32s %s\n' ' op' 'up down stop ps logs build pull restart refresh config reset'
|
||||
@printf ' %-32s %s\n' ' stack' 'dev app db optional'
|
||||
@printf ' %-32s %s\n' ' registry' 'cn global (only up/pull/build/refresh)'
|
||||
@printf '%s\n' ''
|
||||
@printf '%s\n' 'Variables:'
|
||||
@printf ' %-24s %s\n' 'STACK=dev|app|db|optional' 'Compose stack selector'
|
||||
@printf ' %-24s %s\n' 'REGISTRY=auto|global|cn' 'Image registry selector; auto uses .env/DC3_IMAGE_REGISTRY'
|
||||
@@ -123,7 +134,8 @@ help:
|
||||
@printf '%s\n' ''
|
||||
@printf '%s\n' 'Examples:'
|
||||
@printf ' %s\n' 'make init-env'
|
||||
@printf ' %s\n' 'make dev-db'
|
||||
@printf ' %s\n' 'make up-db'
|
||||
@printf ' %s\n' 'make up-db-cn'
|
||||
@printf ' %s\n' 'make up SERVICES="agentic"'
|
||||
@printf ' %s\n' 'make up SERVICES="gateway agentic"'
|
||||
@printf ' %s\n' 'make up GROUP=core'
|
||||
@@ -152,6 +164,17 @@ clean:
|
||||
package:
|
||||
$(MVN) clean package
|
||||
|
||||
test:
|
||||
$(MVN) -B -Dmaven.test.skip=false test
|
||||
|
||||
test-it:
|
||||
$(MVN) -B -Dmaven.test.skip=false -Dskip.unit.tests=true verify
|
||||
|
||||
test-e2e:
|
||||
DC3_E2E=true $(MVN) -B -Dmaven.test.skip=false -Dskip.unit.tests=true -pl dc3-e2e -am -Pe2e verify
|
||||
|
||||
coverage:
|
||||
$(MVN) -B -Dmaven.test.skip=false -pl dc3-coverage -am verify
|
||||
|
||||
build:
|
||||
$(call dc3_compose) build $(SELECTED_SERVICES)
|
||||
@@ -192,11 +215,32 @@ reset:
|
||||
run:
|
||||
$(MVN) -pl "$(RUN_MODULE)" -am spring-boot:run
|
||||
|
||||
dev-db:
|
||||
@$(MAKE) up STACK=db SERVICES= GROUP= REGISTRY=$(REGISTRY) COMPOSE='$(COMPOSE)' COMPOSE_DIR='$(COMPOSE_DIR)' $(MAKE_COMPOSE_OVERRIDE)
|
||||
# Auto-generated compose shortcuts: <op>-<stack>[-<registry>]
|
||||
# op : up down stop ps logs build pull restart refresh config reset
|
||||
# stack : dev app db optional
|
||||
# registry : cn global (only up/pull/build/refresh)
|
||||
# Each shortcut recurses into the base op with STACK/REGISTRY set, so all
|
||||
# existing logic (compose-file resolution, reset confirmation, SERVICES/GROUP
|
||||
# filtering) is reused. Examples: make up-db-cn make logs-dev make down-app
|
||||
COMPOSE_OPS := up down stop ps logs build pull restart refresh config reset
|
||||
COMPOSE_REGISTRY_OPS := up pull build refresh
|
||||
COMPOSE_STACKS := dev app db optional
|
||||
COMPOSE_REGISTRIES := cn global
|
||||
|
||||
dev-optional:
|
||||
@$(MAKE) up STACK=optional SERVICES= GROUP= REGISTRY=$(REGISTRY) COMPOSE='$(COMPOSE)' COMPOSE_DIR='$(COMPOSE_DIR)' $(MAKE_COMPOSE_OVERRIDE)
|
||||
define dc3_stack_target
|
||||
.PHONY: $(1)-$(2)
|
||||
$(1)-$(2):
|
||||
@$$(MAKE) $(1) STACK=$(2) SERVICES='$$(SERVICES)' GROUP='$$(GROUP)' REGISTRY='$$(REGISTRY)' COMPOSE='$$(COMPOSE)' COMPOSE_DIR='$$(COMPOSE_DIR)' $$(MAKE_COMPOSE_OVERRIDE)
|
||||
endef
|
||||
|
||||
define dc3_stack_registry_target
|
||||
.PHONY: $(1)-$(2)-$(3)
|
||||
$(1)-$(2)-$(3):
|
||||
@$$(MAKE) $(1) STACK=$(2) SERVICES='$$(SERVICES)' GROUP='$$(GROUP)' REGISTRY=$(3) COMPOSE='$$(COMPOSE)' COMPOSE_DIR='$$(COMPOSE_DIR)' $$(MAKE_COMPOSE_OVERRIDE)
|
||||
endef
|
||||
|
||||
$(foreach op,$(COMPOSE_OPS),$(foreach st,$(COMPOSE_STACKS),$(eval $(call dc3_stack_target,$(op),$(st)))))
|
||||
$(foreach op,$(COMPOSE_REGISTRY_OPS),$(foreach st,$(COMPOSE_STACKS),$(foreach rg,$(COMPOSE_REGISTRIES),$(eval $(call dc3_stack_registry_target,$(op),$(st),$(rg))))))
|
||||
|
||||
deploy: package
|
||||
cd dc3-api \
|
||||
@@ -204,10 +248,6 @@ deploy: package
|
||||
&& cd ../dc3-common \
|
||||
&& $(MVN_SUB) clean deploy -P deploy
|
||||
|
||||
install-hooks:
|
||||
git config core.hooksPath .githooks
|
||||
@printf '%s\n' 'Enabled .githooks (commit-msg lint active for git commit)'
|
||||
|
||||
tag:
|
||||
dc3/bin/tag.sh
|
||||
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# Copyright 2016-present the IoT DC3 original author or authors.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ALLOWED_TYPES = {
|
||||
"feat",
|
||||
"fix",
|
||||
"perf",
|
||||
"refactor",
|
||||
"docs",
|
||||
"build",
|
||||
"ci",
|
||||
"test",
|
||||
"chore",
|
||||
"style",
|
||||
"security",
|
||||
"revert",
|
||||
}
|
||||
|
||||
WEAK_DESCRIPTIONS = {
|
||||
".",
|
||||
"add",
|
||||
"add comment",
|
||||
"change",
|
||||
"change code",
|
||||
"changes",
|
||||
"fix",
|
||||
"fix bug",
|
||||
"misc",
|
||||
"optimize",
|
||||
"update",
|
||||
"update code",
|
||||
"wip",
|
||||
}
|
||||
|
||||
SUBJECT_RE = re.compile(
|
||||
r"^(?P<type>[a-z]+)"
|
||||
r"(?:\((?P<scope>[a-z0-9][a-z0-9._/-]*(?:,[a-z0-9][a-z0-9._/-]*)*)\))?"
|
||||
r"(?P<breaking>!)?: (?P<description>.+)$"
|
||||
)
|
||||
CJK_RE = re.compile(r"[\u4e00-\u9fff]")
|
||||
FIXUP_RE = re.compile(r"^(fixup|squash)! +", re.IGNORECASE)
|
||||
GENERATED_CHANGELOG_SUBJECT = "docs(release): update generated changelog"
|
||||
MAX_SUBJECT_LENGTH = 100
|
||||
MIN_DESCRIPTION_LENGTH = 10
|
||||
|
||||
|
||||
def read_subject(message_file: Path) -> tuple[str, str]:
|
||||
text = message_file.read_text(encoding="utf-8")
|
||||
lines = [line.rstrip() for line in text.splitlines()]
|
||||
content_lines = [line for line in lines if line.strip() and not line.lstrip().startswith("#")]
|
||||
subject = content_lines[0] if content_lines else ""
|
||||
body = "\n".join(content_lines[1:])
|
||||
while FIXUP_RE.match(subject):
|
||||
subject = FIXUP_RE.sub("", subject, count=1)
|
||||
return subject, body
|
||||
|
||||
|
||||
def is_git_generated_subject(subject: str) -> bool:
|
||||
return subject.startswith("Merge ") or subject.startswith("Revert ")
|
||||
|
||||
|
||||
def normalized_description(description: str) -> str:
|
||||
return re.sub(r"[\s.。!!??_-]+", " ", description.strip().lower()).strip()
|
||||
|
||||
|
||||
def validate_subject(subject: str, body: str) -> list[str]:
|
||||
errors: list[str] = []
|
||||
|
||||
if not subject:
|
||||
return ["Commit subject is required."]
|
||||
if is_git_generated_subject(subject):
|
||||
return []
|
||||
if subject == GENERATED_CHANGELOG_SUBJECT:
|
||||
return []
|
||||
if len(subject) > MAX_SUBJECT_LENGTH:
|
||||
errors.append(f"Commit subject must be at most {MAX_SUBJECT_LENGTH} characters.")
|
||||
if CJK_RE.search(subject):
|
||||
errors.append("Commit subject must be written in English.")
|
||||
|
||||
match = SUBJECT_RE.match(subject)
|
||||
if not match:
|
||||
errors.append("Commit subject must match '<type>(optional-scope): <english summary>'.")
|
||||
return errors
|
||||
|
||||
commit_type = match.group("type")
|
||||
description = match.group("description").strip()
|
||||
breaking = bool(match.group("breaking"))
|
||||
|
||||
if commit_type not in ALLOWED_TYPES:
|
||||
allowed = ", ".join(sorted(ALLOWED_TYPES))
|
||||
errors.append(f"Unsupported commit type '{commit_type}'. Allowed types: {allowed}.")
|
||||
if len(description) < MIN_DESCRIPTION_LENGTH:
|
||||
errors.append(f"Commit description must be at least {MIN_DESCRIPTION_LENGTH} characters.")
|
||||
if normalized_description(description) in WEAK_DESCRIPTIONS:
|
||||
errors.append("Commit description is too vague for generated release notes.")
|
||||
if description[0].islower() is False and not description[0].isdigit():
|
||||
errors.append("Commit description should start with lowercase imperative text.")
|
||||
if breaking and "BREAKING CHANGE:" not in body:
|
||||
errors.append("Breaking-change commits using '!' must include a 'BREAKING CHANGE:' body entry.")
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Validate IoT DC3 commit messages.")
|
||||
parser.add_argument("message_file", type=Path)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
subject, body = read_subject(args.message_file)
|
||||
errors = validate_subject(subject, body)
|
||||
if not errors:
|
||||
return 0
|
||||
|
||||
print("Invalid commit message:", file=sys.stderr)
|
||||
print(f" {subject or '<empty>'}", file=sys.stderr)
|
||||
for error in errors:
|
||||
print(f"- {error}", file=sys.stderr)
|
||||
print("", file=sys.stderr)
|
||||
print("Examples:", file=sys.stderr)
|
||||
print(" feat(agentic): add session cleanup policy", file=sys.stderr)
|
||||
print(" fix(manager): validate tenant scope for device queries", file=sys.stderr)
|
||||
print(" docs(release): update generated changelog", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
# Makefile compose 命令快捷体系
|
||||
|
||||
> 日期:2026-06-18 | 范围:`iot-dc3/Makefile` + 相关文档
|
||||
|
||||
## 背景与动机
|
||||
|
||||
`iot-dc3/Makefile` 的 compose 类操作受三个维度影响:
|
||||
|
||||
| 维度 | 取值 | 作用 |
|
||||
|------|------|------|
|
||||
| `STACK` | `dev` / `app` / `db` / `optional` | 选哪个 compose 文件 |
|
||||
| `REGISTRY` | `auto` / `global` / `cn` | 镜像从哪个仓库拉(global=Docker Hub,cn=阿里云) |
|
||||
| `SERVICES` / `GROUP` | 服务过滤 | 操作哪些服务 |
|
||||
|
||||
但目前只有 `dev-db`、`dev-optional` 两个快捷入口,且都写死、不带 registry 选择。要切换 cn/global 只能 `make dev-db REGISTRY=cn` 手动传环境变量,体验差。
|
||||
|
||||
目标:为**所有** compose 操作建立统一的、命令名里就能表达 `stack`+`registry` 的快捷体系,无需手动传环境变量。
|
||||
|
||||
> 注:GNU make 的 target 名里冒号是语法保留字,`dev:db:cn` 无法作为 target,故采用连字符命名 `dev-db-cn` 形式。
|
||||
|
||||
## 命名约定
|
||||
|
||||
```
|
||||
<op>-<stack>[-<registry>] 连字符分隔
|
||||
op : up down stop ps logs build pull restart refresh config reset
|
||||
stack : dev app db optional
|
||||
registry : cn global ← 仅 up/pull/build/refresh(拉/建镜像的 op)可加
|
||||
```
|
||||
|
||||
- 不带 registry 后缀 → 沿用现状 `REGISTRY=auto`(读 `.env`)。
|
||||
- 生成数量:`11 op × 4 stack` = 44,加 `4 拉镜像 op × 4 stack × 2 registry` = 32,**共 76 个**,全部用 `eval`/`foreach` 自动生成,零手写。
|
||||
|
||||
示例:
|
||||
|
||||
```bash
|
||||
make up-db-cn # = up STACK=db REGISTRY=cn
|
||||
make up-app-global # = up STACK=app REGISTRY=global
|
||||
make logs-dev # = logs STACK=dev
|
||||
make down-optional # = down STACK=optional
|
||||
make pull-app-cn # = pull STACK=app REGISTRY=cn
|
||||
make restart-db # = restart STACK=db
|
||||
make config-db # = config STACK=db
|
||||
make up-db-cn SERVICES="postgres" # 仍可叠加服务过滤
|
||||
```
|
||||
|
||||
## 实现:递归复用,零逻辑重复
|
||||
|
||||
生成的 target 不重新实现逻辑,而是递归 `$(MAKE) <op> STACK=… REGISTRY=…` 调用已有基础规则(参数化现有 `dev-db` 的转发写法)。
|
||||
|
||||
```makefile
|
||||
# <op>-<stack> → <op> STACK=<stack>,REGISTRY 沿用当前值
|
||||
define gen_stack_target
|
||||
.PHONY: $(1)-$(2)
|
||||
$(1)-$(2):
|
||||
@$$(MAKE) $(1) STACK=$(2) SERVICES='$$(SERVICES)' GROUP='$$(GROUP)' REGISTRY='$$(REGISTRY)' COMPOSE='$$(COMPOSE)' COMPOSE_DIR='$$(COMPOSE_DIR)' $$(MAKE_COMPOSE_OVERRIDE)
|
||||
endef
|
||||
|
||||
# <op>-<stack>-<registry> → <op> STACK=<stack> REGISTRY=<registry>
|
||||
define gen_stack_registry_target
|
||||
.PHONY: $(1)-$(2)-$(3)
|
||||
$(1)-$(2)-$(3):
|
||||
@$$(MAKE) $(1) STACK=$(2) SERVICES='$$(SERVICES)' GROUP='$$(GROUP)' REGISTRY=$(3) COMPOSE='$$(COMPOSE)' COMPOSE_DIR='$$(COMPOSE_DIR)' $$(MAKE_COMPOSE_OVERRIDE)
|
||||
endef
|
||||
|
||||
OPS := up down stop ps logs build pull restart refresh config reset
|
||||
REGISTRY_OPS := up pull build refresh
|
||||
STACKS := dev app db optional
|
||||
REGISTRIES := cn global
|
||||
|
||||
$(foreach op,$(OPS),$(foreach st,$(STACKS),$(eval $(call gen_stack_target,$(op),$(st)))))
|
||||
$(foreach op,$(REGISTRY_OPS),$(foreach st,$(STACKS),$(foreach rg,$(REGISTRIES),$(eval $(call gen_stack_registry_target,$(op),$(st),$(rg))))))
|
||||
```
|
||||
|
||||
直接收益:
|
||||
|
||||
- `COMPOSE_FILE` 解析、`SELECTED_SERVICES`、`dc3_compose` 全自动复用。
|
||||
- `reset-db` 等**自动继承** `reset` 规则里的 `CONFIRM_RESET_VOLUMES` 保护。
|
||||
- `SERVICES`/`GROUP` 仍可叠加,默认空=全部服务。
|
||||
- 加新 stack / op 只需改一个列表变量。
|
||||
|
||||
## 删除旧名
|
||||
|
||||
- 移除 `dev-db` / `dev-optional` 两个 target 规则。
|
||||
- 从 `.PHONY` 行移除 `dev-db dev-optional`(生成的快捷名各自在模板内声明 `.PHONY`)。
|
||||
|
||||
## help 重写
|
||||
|
||||
新增"Compose shortcuts"一节,说明命名规则 + 取值表 + 例子;`Examples` 区把 `make dev-db` 改为 `make up-db` 等。形如:
|
||||
|
||||
```
|
||||
Compose shortcuts (auto-generated):
|
||||
make <op>-<stack>[-<registry>]
|
||||
op : up down stop ps logs build pull restart refresh config reset
|
||||
stack : dev app db optional
|
||||
registry : cn global (only up/pull/build/refresh)
|
||||
e.g. make up-db-cn make logs-dev make pull-app-global make down-optional
|
||||
```
|
||||
|
||||
## 文档同步(13 文件)
|
||||
|
||||
把已删除的 `make dev-db` / `make dev-optional` 替换为 `make up-db` / `make up-optional`:
|
||||
|
||||
- `github/AGENTS.md`
|
||||
- `github/CLAUDE.md`
|
||||
- `iot-dc3/.claude/skills/dc3-stack-test/SKILL.md`
|
||||
- `iot-dc3/AGENTS.md`
|
||||
- `iot-dc3/CONTRIBUTING.md`
|
||||
- `iot-dc3/dc3/doc/USAGE.md`
|
||||
- `iot-dc3/docs/guide/troubleshooting.md`
|
||||
- `iot-dc3/docs/quickstart/environment.md`
|
||||
- `iot-dc3/docs/quickstart/index.md`
|
||||
- `iot-dc3/README.ja.md`
|
||||
- `iot-dc3/README.md`
|
||||
- `iot-dc3/README.vi.md`
|
||||
- `iot-dc3/README.zh.md`
|
||||
|
||||
规则:
|
||||
|
||||
- **必须**替换被删的 `dev-db` / `dev-optional`(否则文档示例会报 "No rule to make target")。
|
||||
- `make up STACK=db` / `REGISTRY=cn` 这类写法**仍有效**(基础 op 保留),不强制替换;仅在主 README / AGENTS 的"快速开始"处主推新快捷命令。
|
||||
- `.env.example` 的 `REGISTRY=cn` 注释保留(机制不变)。
|
||||
|
||||
## 非目标(YAGNI)
|
||||
|
||||
- 不做跨 stack 聚合命令(一条命令同时起 db+optional+dev)。
|
||||
- 不引入交互式选择。
|
||||
- `REGISTRY=auto` 读 `.env` 的现有机制不变。
|
||||
|
||||
## 验证
|
||||
|
||||
- `make -n up-db-cn` → 展开含 `STACK=db REGISTRY=cn`。
|
||||
- `make -n logs-dev` → 展开含 `STACK=dev`,且不含 `REGISTRY=cn/global`(无 registry 后缀)。
|
||||
- `make config-db` 实跑能渲染 db compose 配置。
|
||||
- `make reset-db`(无 `CONFIRM_RESET_VOLUMES=true`)被拒绝。
|
||||
- `grep -rn "make dev-db\|make dev-optional" <13 文件>` 无残留。
|
||||
Reference in New Issue
Block a user