From 348d3802e8c0d32f0f77579851adfcebcd76f63f Mon Sep 17 00:00:00 2001 From: Evgeniy Frolov Date: Mon, 22 Jun 2026 14:39:37 +0300 Subject: [PATCH 1/8] chore(ci): bump Kubernetes version (#7595) Signed-off-by: Evgeniy Frolov --- .github/workflows/_test_e2e_per-k8s-version.yml | 2 +- ..._test_integration_per-k8s-version-and-container-registry.yml | 2 +- .github/workflows/_test_integration_per-k8s-version.yml | 2 +- .gitignore | 2 +- Taskfile.dist.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/_test_e2e_per-k8s-version.yml b/.github/workflows/_test_e2e_per-k8s-version.yml index b8858614a8..645554c59c 100644 --- a/.github/workflows/_test_e2e_per-k8s-version.yml +++ b/.github/workflows/_test_e2e_per-k8s-version.yml @@ -37,7 +37,7 @@ jobs: strategy: fail-fast: false matrix: - kubeVersion: [1.29.14, 1.31.6] + kubeVersion: [1.34.8, 1.36.1] runs-on: ubuntu-22.04 timeout-minutes: ${{ inputs.timeout }} diff --git a/.github/workflows/_test_integration_per-k8s-version-and-container-registry.yml b/.github/workflows/_test_integration_per-k8s-version-and-container-registry.yml index 395168f38b..0de01e718d 100644 --- a/.github/workflows/_test_integration_per-k8s-version-and-container-registry.yml +++ b/.github/workflows/_test_integration_per-k8s-version-and-container-registry.yml @@ -25,7 +25,7 @@ jobs: matrix: os: - ${{ inputs.linuxAmd64Runner }} - kubeVersion: [1.29.14, 1.31.6] + kubeVersion: [1.34.8, 1.36.1] runs-on: ${{ matrix.os }} timeout-minutes: 60 env: diff --git a/.github/workflows/_test_integration_per-k8s-version.yml b/.github/workflows/_test_integration_per-k8s-version.yml index c5dc136da5..c85d6de474 100644 --- a/.github/workflows/_test_integration_per-k8s-version.yml +++ b/.github/workflows/_test_integration_per-k8s-version.yml @@ -25,7 +25,7 @@ jobs: matrix: os: - ${{ inputs.linuxAmd64Runner }} - kubeVersion: [1.29.14, 1.31.6] + kubeVersion: [1.34.8, 1.36.1] runs-on: ${{ matrix.os }} timeout-minutes: 60 steps: diff --git a/.gitignore b/.gitignore index a25ce70610..996f407261 100644 --- a/.gitignore +++ b/.gitignore @@ -50,4 +50,4 @@ buildah-test /playground/s3_registry/data /.sisyphus -/.opencode \ No newline at end of file +/.opencode diff --git a/Taskfile.dist.yaml b/Taskfile.dist.yaml index fc29517fc9..16d40c899f 100644 --- a/Taskfile.dist.yaml +++ b/Taskfile.dist.yaml @@ -27,7 +27,7 @@ vars: devBinary: './bin/werf{{if (eq .targetOS "windows")}}.exe{{end}}' withCoverageBinary: './bin/werf-with-coverage{{if (eq .targetOS "windows")}}.exe{{end}}' package: "github.com/werf/werf/v2/cmd/werf" - kubeVersion: '{{.kubeVersion | default "1.33.1"}}' + kubeVersion: '{{.kubeVersion | default "1.36.1"}}' goTags: "dfrunsecurity dfrunnetwork dfrunmount dfssh containers_image_openpgp" goLDFlags: "-s -w -X github.com/werf/werf/v2/pkg/werf.Version={{.version}}" From 0ca57cd63744a6b61756172384eecdf5fdfa4cc3 Mon Sep 17 00:00:00 2001 From: Evgeniy Frolov Date: Fri, 19 Jun 2026 12:05:37 +0300 Subject: [PATCH 2/8] chore(docs): clarify usage for cleanup Signed-off-by: Evgeniy Frolov --- docs/pages_en/usage/cleanup/cr_cleanup.md | 6 ++++-- docs/pages_ru/usage/cleanup/cr_cleanup.md | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/pages_en/usage/cleanup/cr_cleanup.md b/docs/pages_en/usage/cleanup/cr_cleanup.md index bfff1574a3..20796fb946 100644 --- a/docs/pages_en/usage/cleanup/cr_cleanup.md +++ b/docs/pages_en/usage/cleanup/cr_cleanup.md @@ -174,7 +174,7 @@ The documentation section about ["Saving the result of work"](#generate-keep-lis By default, werf uses the [_Docker Registry API_](https://docs.docker.com/registry/spec/api/) for deleting tags. The user must be authenticated and have a sufficient set of permissions. If the _Docker Registry API_ isn't supported and tags are deleted using the native API, then some additional container registry-specific actions are required on the user's part. | | | -|-----------------------------|:---------------------------:| +| --------------------------- | :-------------------------: | | _AWS ECR_ | [***ok**](#aws-ecr) | | _Azure CR_ | [***ok**](#azure-cr) | | _Default_ | **ok** | @@ -238,7 +238,9 @@ You can use the `--repo-github-token` option or the corresponding environment va werf uses the _GitLab container registry API_ or _Docker Registry API_ (depending on the GitLab version) to delete tags. -> The privileges of the temporary CI job token ($CI_JOB_TOKEN) are not sufficient to delete tags. Therefore, the user must create a dedicated token in the Access Token section, select api in the Scope section, and ensure the role of Maintainer or Owner is assigned before using it for authorization +> You can use the temporary CI job token (`$CI_JOB_TOKEN`) to delete tags if the user who started the job has sufficient permissions in the project and the project Job token permissions allow the required access. +> +> If these conditions are not met (for example, because of cross-project restrictions or an insufficient role), use a dedicated Project/Personal Access Token with the `api` scope. ## Saving the result of work diff --git a/docs/pages_ru/usage/cleanup/cr_cleanup.md b/docs/pages_ru/usage/cleanup/cr_cleanup.md index f3b4057406..27a08f228e 100644 --- a/docs/pages_ru/usage/cleanup/cr_cleanup.md +++ b/docs/pages_ru/usage/cleanup/cr_cleanup.md @@ -174,7 +174,7 @@ my-custom-tag По умолчанию при удалении тегов werf использует [_Docker Registry API_](https://docs.docker.com/registry/spec/api/) и от пользователя требуется только авторизация с использованием доступов с достаточным набором прав. Если же удаление посредством _Docker Registry API_ не поддерживается и оно реализуется в нативном API container registry, то от пользователя могут потребоваться специфичные для используемого container registry действия. | | | -|-----------------------------|:---------------------------:| +| --------------------------- | :-------------------------: | | _AWS ECR_ | [***ок**](#aws-ecr) | | _Azure CR_ | [***ок**](#azure-cr) | | _Default_ | **ок** | @@ -237,7 +237,9 @@ HUB_TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": При удалении тегов werf использует _GitLab container registry API_ или _Docker Registry API_ в зависимости от версии GitLab. -> Прав временного токена CI-задания ($CI_JOB_TOKEN) недостаточно для удаления тегов, поэтому пользователю необходимо создать специальный токен в разделе Access Token, выбрать api в секции Scope и назначить роль Maintainer или Owner перед использованием его для авторизации +> Для удаления тегов можно использовать временный токен CI-задания (`$CI_JOB_TOKEN`), если пользователь, запустивший задание, имеет достаточные права в проекте, а настройки Job token permissions разрешают требуемый доступ. +> +> Если эти условия не выполняются (например, из-за ограничений межпроектного доступа или недостаточной роли), используйте отдельный Project/Personal Access Token со scope `api`. ## Сохранение результата работы From b1933b36118fb36a5bab847a93c56bc9196c13b1 Mon Sep 17 00:00:00 2001 From: Evgeniy Frolov Date: Tue, 23 Jun 2026 15:27:56 +0300 Subject: [PATCH 3/8] fix(build, buildah, dockerfile, staged): resolve staged Dockerfile RUN --mount from= to built image (#7594) Signed-off-by: Evgeniy Frolov --- pkg/build/stage/instruction/export_test.go | 4 + pkg/build/stage/instruction/run.go | 10 ++ pkg/build/stage/instruction/run_ai_test.go | 111 +++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 pkg/build/stage/instruction/run_ai_test.go diff --git a/pkg/build/stage/instruction/export_test.go b/pkg/build/stage/instruction/export_test.go index 021e2fef31..fecc6d26c6 100644 --- a/pkg/build/stage/instruction/export_test.go +++ b/pkg/build/stage/instruction/export_test.go @@ -23,3 +23,7 @@ func ExportUserCommands(stg *User) (backend, source instructions.UserCommand) { func ExportStopSignalCommands(stg *StopSignal) (backend, source instructions.StopSignalCommand) { return stg.backendInstruction.StopSignalCommand, *stg.instruction.Data } + +func ExportRunMounts(stg *Run) []*instructions.Mount { + return stg.backendInstruction.GetMounts() +} diff --git a/pkg/build/stage/instruction/run.go b/pkg/build/stage/instruction/run.go index 3d23cfbfa9..a303d21c4a 100644 --- a/pkg/build/stage/instruction/run.go +++ b/pkg/build/stage/instruction/run.go @@ -33,6 +33,16 @@ func (stg *Run) ExpandInstruction(c stage.Conveyor, env map[string]string) error } // Setup RUN envs after 2nd stage expansion stg.backendInstruction.Envs = EnvToSortedArr(stg.GetExpandedEnv(c)) + + for _, mnt := range instructions.GetMounts(stg.instruction.Data) { + if mnt.From == "" { + continue + } + if ds := stg.instruction.GetDependencyByStageRef(mnt.From); ds != nil { + mnt.From = c.GetImageNameForLastImageStage(stg.TargetPlatform(), ds.GetWerfImageName()) + } + } + return nil } diff --git a/pkg/build/stage/instruction/run_ai_test.go b/pkg/build/stage/instruction/run_ai_test.go new file mode 100644 index 0000000000..0812ebee09 --- /dev/null +++ b/pkg/build/stage/instruction/run_ai_test.go @@ -0,0 +1,111 @@ +package instruction_test + +import ( + "bytes" + "fmt" + + "github.com/moby/buildkit/frontend/dockerfile/instructions" + "github.com/moby/buildkit/frontend/dockerfile/parser" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/werf/werf/v2/pkg/build/stage" + "github.com/werf/werf/v2/pkg/build/stage/instruction" +) + +func parseRunCommandAI(dockerfileText string) *instructions.RunCommand { + p, err := parser.Parse(bytes.NewReader([]byte(dockerfileText))) + Expect(err).To(Succeed()) + + dockerStages, _, err := instructions.Parse(p.AST) + Expect(err).To(Succeed()) + Expect(dockerStages).NotTo(BeEmpty()) + + for _, cmd := range dockerStages[len(dockerStages)-1].Commands { + if run, ok := cmd.(*instructions.RunCommand); ok { + return run + } + } + + Fail("no RUN command found in dockerfile") + return nil +} + +func newRunStageAI(runCommand *instructions.RunCommand, dependencyStages []string) *instruction.Run { + return instruction.NewRun( + NewDockerfileStageInstructionWithDependencyStages(runCommand, dependencyStages), + nil, false, + &stage.BaseStageOptions{ImageName: "example-image", ProjectName: "example-project"}, + nil, "", + ) +} + +var _ = Describe("TestAI_ RUN mount from stage resolution", func() { + const resolvedOsImage = "ghcr.io/werf/instruction-test:a71052baf9c6ace8171e59a2ae5ea1aede3fb89aa95d160ec354b205-1661868399091" + + It("TestAI_ resolves --mount from= to the built werf stage image in the backend instruction", func(ctx SpecContext) { + stg := newRunStageAI( + parseRunCommandAI("FROM alpine AS os\nRUN --mount=type=bind,from=os,source=/apk,target=/apk true\n"), + []string{"os"}, + ) + + conveyor := stage.NewConveyorStub( + stage.NewGiterminismManagerStub(stage.NewLocalGitRepoStub("test"), stage.NewGiterminismInspectorStub()), + map[string]string{"/stage/os": resolvedOsImage}, + nil, nil, + ) + + Expect(stg.ExpandDependencies(ctx, conveyor, map[string]string{})).To(Succeed()) + + mounts := instruction.ExportRunMounts(stg) + Expect(mounts).To(HaveLen(1)) + Expect(mounts[0].From).To(Equal(resolvedOsImage)) + }) + + It("TestAI_ leaves external --mount from= references unchanged", func(ctx SpecContext) { + stg := newRunStageAI( + parseRunCommandAI("FROM alpine\nRUN --mount=type=bind,from=alpine:3.19,source=/etc,target=/etc true\n"), + nil, + ) + + conveyor := stage.NewConveyorStub( + stage.NewGiterminismManagerStub(stage.NewLocalGitRepoStub("test"), stage.NewGiterminismInspectorStub()), + nil, nil, nil, + ) + + Expect(stg.ExpandDependencies(ctx, conveyor, map[string]string{})).To(Succeed()) + + mounts := instruction.ExportRunMounts(stg) + Expect(mounts).To(HaveLen(1)) + Expect(mounts[0].From).To(Equal("alpine:3.19")) + }) + + digestFor := func(ctx SpecContext, resolvedImage string) string { + stg := newRunStageAI( + parseRunCommandAI("FROM alpine AS os\nRUN --mount=type=bind,from=os,source=/apk,target=/apk true\n"), + []string{"os"}, + ) + + conveyor := stage.NewConveyorStub( + stage.NewGiterminismManagerStub(stage.NewLocalGitRepoStub("test"), stage.NewGiterminismInspectorStub()), + map[string]string{"/stage/os": resolvedImage}, + nil, nil, + ) + + Expect(stg.ExpandDependencies(ctx, conveyor, map[string]string{})).To(Succeed()) + + digest, err := stg.GetDependencies(ctx, conveyor, stage.NewContainerBackendStub(), nil, nil, nil) + Expect(err).To(Succeed()) + return digest + } + + It("TestAI_ digest reflects the resolved stage image and is stable for identical inputs", func(ctx SpecContext) { + digest1 := digestFor(ctx, resolvedOsImage) + digest2 := digestFor(ctx, resolvedOsImage) + Expect(digest1).To(Equal(digest2)) + + changedDigest := digestFor(ctx, "ghcr.io/werf/instruction-test:4930d562bfbee9c931413c826137d49eff6a2e7d39519c1c9488a747-1655913653892") + fmt.Printf("digest: %s, changedDigest: %s\n", digest1, changedDigest) + Expect(changedDigest).NotTo(Equal(digest1)) + }) +}) From 6cea67a287f25b583e3f0977a0d2535a712b49d3 Mon Sep 17 00:00:00 2001 From: Evgeniy Frolov Date: Tue, 23 Jun 2026 15:28:25 +0300 Subject: [PATCH 4/8] chore(ci): configure registry cleanup with prod kubeconfig (#7596) Signed-off-by: Evgeniy Frolov --- .github/workflows/docs_cleanup-registry.yml | 43 ++++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs_cleanup-registry.yml b/.github/workflows/docs_cleanup-registry.yml index b89fc92c92..84506c56aa 100644 --- a/.github/workflows/docs_cleanup-registry.yml +++ b/.github/workflows/docs_cleanup-registry.yml @@ -15,12 +15,49 @@ jobs: cleanup: if: github.repository == 'werf/werf' runs-on: prod-github-runner-0 + permissions: + id-token: write + contents: read + packages: write steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 0 + - name: Authenticate in Seguro + id: vault + uses: hashicorp/vault-action@v4 + with: + url: https://seguro.flant.com + path: github + role: werf-web + method: jwt + jwtGithubAudience: github-access-aud + exportToken: true + + - name: Read and normalize kubeconfig from Bob + id: kubeconfig + run: | + set -euo pipefail + + response="$(curl -fsSL -H "X-Vault-Token: $VAULT_TOKEN" "https://seguro.flant.com/v1/projects/data/b454e6aa-39f0-45f4-aa7c-a9465ab154cb/KUBE_CONFIG_RU")" + secret_value="$(printf '%s' "$response" | jq -r '.data.data["kube.config"]')" + + if [[ -z "$secret_value" || "$secret_value" == "null" ]]; then + echo "Bob kubeconfig secret is empty" >&2 + exit 1 + fi + + if printf '%s' "$secret_value" | base64 -d >/tmp/docs-kubeconfig-decoded 2>/dev/null && grep -q '^apiVersion:' /tmp/docs-kubeconfig-decoded; then + kubeconfig_base64="$secret_value" + else + kubeconfig_base64="$(printf '%s' "$secret_value" | base64 | tr -d '\n')" + fi + + echo "::add-mask::$kubeconfig_base64" + echo "kubeconfig_base64=$kubeconfig_base64" >> "$GITHUB_OUTPUT" + - name: Install werf uses: werf/actions/install@v2 with: @@ -31,7 +68,9 @@ jobs: . $(werf ci-env github --as-file) werf cleanup env: + WERF_NAMESPACE: werfio-production WERF_DIR: docs + WERF_REPO: ghcr.io/${{ github.repository_owner }}/werfio + WERF_ENV: production + WERF_KUBE_CONFIG_BASE64: ${{ steps.kubeconfig.outputs.kubeconfig_base64 }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - WERF_REPO_GITHUB_TOKEN: ${{ secrets.WERF_IN_IMAGE_CLEANUP_GHCR }} - WERF_KUBE_CONFIG_BASE64: ${{ secrets.KUBECONFIG_BASE64_DEV }} From a622d30c5dee1c3d0e70fbc254b0c1488d31a43a Mon Sep 17 00:00:00 2001 From: flant-team-sysdev Date: Tue, 23 Jun 2026 15:28:56 +0300 Subject: [PATCH 5/8] chore(main): release 2.73.0 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf9c54281e..f84236fe9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [2.73.0](https://github.com/werf/werf/compare/v2.72.2...v2.73.0) (2026-06-23) + + +### Features + +* **deploy:** move `dockerconfigjson` to .global.werf ([#7583](https://github.com/werf/werf/issues/7583)) ([79d90cb](https://github.com/werf/werf/commit/79d90cb69f563a2ec7b109de5481c4eba45f9722)) + + +### Bug Fixes + +* **build, buildah, dockerfile, staged:** resolve staged Dockerfile RUN --mount from=<stage> to built image ([#7594](https://github.com/werf/werf/issues/7594)) ([b1933b3](https://github.com/werf/werf/commit/b1933b36118fb36a5bab847a93c56bc9196c13b1)) + ## [2.72.2](https://github.com/werf/werf/compare/v2.72.1...v2.72.2) (2026-06-18) From 32c2ff8565e2ca058a77885caab8ba385e04ec97 Mon Sep 17 00:00:00 2001 From: Aleksei Igrychev Date: Tue, 23 Jun 2026 14:06:08 +0100 Subject: [PATCH 6/8] chore(release): 2 alpha,beta,ea,stable --- trdl_channels.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/trdl_channels.yaml b/trdl_channels.yaml index 9595524c70..78d63ca624 100644 --- a/trdl_channels.yaml +++ b/trdl_channels.yaml @@ -38,12 +38,12 @@ groups: - name: "2" channels: - name: alpha - version: 2.72.2 + version: 2.73.0 - name: beta - version: 2.72.1 + version: 2.72.2 - name: ea - version: 2.71.0 + version: 2.72.2 - name: stable - version: 2.70.0 + version: 2.71.0 - name: rock-solid version: 2.70.0 From c48df853a061d36ce84fe22a5602c1cc5df762a5 Mon Sep 17 00:00:00 2001 From: Aleksei Igrychev Date: Tue, 23 Jun 2026 14:57:28 +0100 Subject: [PATCH 7/8] chore: force release 2.73.0-dk Release-As: v2.73.0-dk Signed-off-by: Aleksei Igrychev From a40ce978616b8a71664e7466af9b00cc1248d3d2 Mon Sep 17 00:00:00 2001 From: Aleksei Igrychev Date: Tue, 23 Jun 2026 15:26:44 +0100 Subject: [PATCH 8/8] docs(skills): merge-upstream keeps CHANGELOG untouched, release-please owns it Signed-off-by: Aleksei Igrychev --- .agents/skills/merge-upstream/SKILL.md | 43 +++++++++----------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/.agents/skills/merge-upstream/SKILL.md b/.agents/skills/merge-upstream/SKILL.md index 3b2ef7d825..7fc8ce4e12 100644 --- a/.agents/skills/merge-upstream/SKILL.md +++ b/.agents/skills/merge-upstream/SKILL.md @@ -9,9 +9,10 @@ description: Merge werf upstream into the deckhouse/delivery-kit fork. Resolves - **Upstream** = `werf/werf` (fetch/merge source). **Fork** = `deckhouse/delivery-kit` (push target). - Remote names vary per clone, so Step 0 resolves both by URL into `$UPSTREAM` / `$FORK`. -- `CHANGELOG.md` is release-please-managed (`release-type: go`, runs on push to `main`). Only `-dk` - entries are authored by hand; bare upstream blocks (`## [X.Y.Z]`) already in history stay, but - you never add new ones. +- `CHANGELOG.md` is release-please-managed (`release-type: go`, runs on push to `main`). + Nothing from `upstream/main` ever lands in it: on conflict you always take ours and never copy, + author, or prepend any entry — the changelog is release-please's job on push to `main`, not the + agent's. The agent only pins the release version via an empty `Release-As` commit (Step 2). - Requires `gh` authenticated and a clean working tree. The agent merges, resolves conflicts, and opens a PR — it never pushes to the fork's `main`. @@ -45,7 +46,8 @@ merge subject identical with or without conflicts. Resolve conflicts: - **`CHANGELOG.md`** — always take ours: `git checkout --ours CHANGELOG.md && git add CHANGELOG.md`. - Upstream changelog changes are dropped; the `-dk` entry is authored in Step 2. + Upstream changelog changes are dropped. Do NOT author or prepend any entry — release-please + generates the changelog on push to `main`. - **`go.mod` / `go.sum`** — resolve obvious parts, then `go mod tidy && git add go.mod go.sum`. Never blindly take one side. - **Any other file** — do not blanket-take upstream; it can silently revert delivery-kit @@ -58,31 +60,16 @@ Stage resolved tracked files only, then commit: git add -u && git commit --no-edit ``` -### 2. Author the `-dk` changelog entry and force the release version +### 2. Force the release version (no changelog) -Do this after a conflict-free merge exists. Use the Step 1 preview for the commit list (and -`gh pr view --json commits` if a delivery-kit PR URL was given). - -Skip release-please noise (`chore(main): release …`, `chore(release): N alpha,beta`). +Do NOT author or prepend anything in `CHANGELOG.md` — release-please generates it on push to +`main`. The only release artifact the agent adds is an empty `Release-As` commit that pins the +exact `-dk` version (release-please would otherwise infer it from commit history). **Determine the next `-dk` version** from the upstream base being merged: if upstream moved `2.72.x → 2.73.0`, it is `2.73.0-dk`; if the upstream base is unchanged and you add only fork-side fixes, bump the `-dk` patch. Never blindly +1 the latest `-dk` patch across an upstream minor/major. -**Prepend the changelog block** below `# Changelog` (today's date), then commit: - -``` -## [X.Y.Z-dk](https://github.com/deckhouse/delivery-kit/compare/vPREV-dk...vX.Y.Z-dk) (YYYY-MM-DD) -### Features / Bug Fixes — using deckhouse/delivery-kit links, not werf/werf -``` - -```bash -git add CHANGELOG.md && git commit -m "chore(release): resolve changelog for X.Y.Z-dk" -``` - -**Force the Release Please version** with an empty commit carrying `Release-As`. This overrides the -SemVer bump Release Please would calculate from commit history and pins the exact `-dk` version: - ```bash git commit --allow-empty -m "chore: force release X.Y.Z-dk @@ -90,7 +77,7 @@ Release-As: vX.Y.Z-dk" ``` `Release-As: vX.Y.Z-dk` must be in the **commit body** (blank line after subject), not the subject -line. The value must include the `v` prefix. Use the same version as the changelog entry above. +line. The value must include the `v` prefix. ### 3. Regenerate docs, build, test @@ -108,14 +95,14 @@ If build or tests fail, stop and resolve (or surface for a maintainer) before th ```bash git grep -q '^<<<<<<<' && { echo "ABORT: conflict markers"; exit 1; } # MUST find none -head -5 CHANGELOG.md # top MUST be the new -dk block +git diff "$FORK/main" -- CHANGELOG.md # MUST be empty (nothing from upstream) git status # MUST be clean git push -u "$FORK" chore/release/merge-werf-upstream gh pr create --repo deckhouse/delivery-kit --base main \ --head chore/release/merge-werf-upstream \ --title "chore(release): merge werf upstream into delivery-kit (X.Y.Z-dk)" \ - --body "Sync werf upstream. CHANGELOG.md kept -dk-only. New release entry: X.Y.Z-dk." + --body "Sync werf upstream. CHANGELOG.md unchanged; release-please generates it on merge. Release pinned to X.Y.Z-dk via Release-As." ``` The agent stops after opening the PR; a maintainer reviews and merges. @@ -129,7 +116,7 @@ To recover before pushing: `git merge --abort`, or discard the branch with `git-commit-message`, and `pull-request-name` skills for any other naming. - ALWAYS work on the `chore/release/...` branch and finish with a PR; NEVER push to the fork's `main`. - ALWAYS run `task doc:gen`, `task build`, `task test:unit` before the PR; NEVER open it with a broken build or remaining conflict markers. -- ALWAYS add an empty `Release-As: vX.Y.Z-dk` commit (Step 2) so Release Please proposes the correct version; NEVER rely on SemVer bump inference from commit history alone. -- CHANGELOG: NEVER add a bare upstream block or reorder existing entries; only prepend one `-dk` block, and take ours (`--ours`) on conflict. +- CHANGELOG: NEVER copy, author, prepend, or reorder any entry; take ours (`--ours`) on conflict and leave it byte-identical to `$FORK/main`. The changelog is release-please's job. +- ALWAYS add an empty `Release-As: vX.Y.Z-dk` commit (Step 2) so release-please pins the correct version; NEVER author a changelog entry for it — release-please generates the changelog on push to `main`. - NEVER `git add .`; stage only resolved tracked files. - NEVER blanket-resolve non-CHANGELOG conflicts toward upstream; stop and ask a human.