Skip to content

fix(tokenless): fail RPM build when spec lacks anolisa-component Provides - #2868

Closed
Forrest-ly wants to merge 2 commits into
alibaba:mainfrom
Forrest-ly:fix/tokenless-provides-build-assertion
Closed

fix(tokenless): fail RPM build when spec lacks anolisa-component Provides#2868
Forrest-ly wants to merge 2 commits into
alibaba:mainfrom
Forrest-ly:fix/tokenless-provides-build-assertion

Conversation

@Forrest-ly

@Forrest-ly Forrest-ly commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Why

The released tokenless 0.7.12 RPM still lacks Provides: anolisa-component(tokenless) even though the spec fix (#2576) landed on main. The in-repo build path (scripts/rpm-build.sh) never asserted the capability for tokenless, so a spec baseline that drifted away from the fix could build and ship silently. build_cosh_ng already guards this (see its identity + Provides + manifest checks); tokenless did not. In addition, the nightly pipeline (docker-nightly.yaml_rpm-build.yaml) never runs scripts/rpm-build.sh at all — it processes the archived spec and calls rpmbuild directly — so the in-repo script fix alone leaves the nightly artifact path unprotected.

Fixes #2836.

What changed

Commit b6181ff — in-repo build guard (scripts/rpm-build.sh)

Added a component-contract guard to build_tokenless in scripts/rpm-build.sh, mirroring the existing build_cosh_ng pattern:

  • Derive the component name from src/tokenless/.anolisa/component.toml.in.
  • Fail the build if the component name does not match the RPM package name.
  • Fail the build unless tokenless.spec.in contains an exact Provides: anolisa-component(<component>) line.

No change to the shipped spec content (the Provides: line already exists at src/tokenless/tokenless.spec.in); this only makes a future regression fail loudly at build time instead of shipping.

Commit f359ab9 — nightly workflow guard (.github/workflows/_rpm-build.yaml)

The checked-in nightly pipeline produces tokenless RPMs through docker-nightly.yaml_rpm-build.yaml, which processes the archived spec and calls rpmbuild directly, so the build_tokenless guard above never runs there: deleting the Provides: line would still let the nightly publish an RPM with the original defect. This commit closes the gap with the same component-contract assertion, gated on inputs.component == 'tokenless' so other components are unaffected:

  • New Verify tokenless component contract step before Build RPM (_rpm-build.yaml:252): derive the component name from .anolisa/component.toml.in in the source archive, verify it matches the RPM Name: of the processed spec, and require an exact Provides: anolisa-component(<name>) line in the processed spec.
  • Extend Collect RPM artifacts: for tokenless, verify every built RPM actually publishes the anolisa-component(<name>) capability via rpm -qp --provides, catching malformed Provides lines that pass the text guard but are silently dropped by rpmbuild (mirrors the existing agentsight verification hook).

Archive layout note: package-source ships the full src/tokenless tree plus the make generate-component-contract output, so the extracted archive contains both the .anolisa/component.toml.in template read by the guard and the generated .anolisa/component.toml; the guard's find pattern matches only the .in template.

Validation

Environment (public info only): Linux Alibaba Cloud Linux 3, x86_64; GNU bash 4.4.20; GNU Make 4.2.1; rustc/cargo 1.96.0; node v22.21.1 / npm 10.9.4; rpmbuild 4.14.3; python3 + PyYAML (YAML syntax check only).

Commit b6181ff — in-repo guard

Real runs performed (not simulated):

Check Command Result
Syntax bash -n scripts/rpm-build.sh pass
Positive (guard passes on current tree) bash scripts/rpm-build.sh tokenless full RPM build succeeds
Built RPM carries capability rpm -qp --provides <built rpm> anolisa-component(tokenless) present
Negative (missing Provides) removed the Provides: line, re-ran build fails fast: tokenless spec must provide anolisa-component(tokenless), exit 1
Negative (identity drift) renamed component to tokenlessx, re-ran build fails fast: tokenless identity mismatch: RPM name 'tokenless', component name 'tokenlessx', exit 1

Positive build output: tokenless-0.7.13-1.al8.x86_64.rpm; rpm -qp --provides returns anolisa-component(tokenless) as the first capability. Negative cases were run against temporary edits and reverted.

Re-run on the final tree (f359ab9): bash scripts/rpm-build.sh tokenless exits 0, writes tokenless-0.7.13-1.al8.x86_64.rpm, and rpmbuild reports Provides: anolisa-component(tokenless) — confirming the commit-1 guard still passes and commit 2 does not alter the in-repo path.

Commit f359ab9 — nightly workflow guard

The nightly path only executes in CI, so each new step body was extracted verbatim from the workflow YAML (only ${{ inputs.* }} substituted, isolated $HOME instead of the runner home) and run against a faithful local reproduction of the nightly inputs: .github/actions/package-source reproduced for tokenless (copy src/tokenless/ tree → make generate-component-contract → tar into tokenless-0.7.13.nightly.tar.gz; the rtk vendoring step was skipped because it only affects third_party/rtk, which the guard never reads), then Prepare source and spec run verbatim (extract archive, copy tarball to SOURCES, process tokenless.spec.intokenless.spec with sed s/@VERSION@/0.7.13/). The archive was verified to contain both .anolisa/component.toml.in and the generated .anolisa/component.toml.

Check Result
YAML syntax: _rpm-build.yaml, docker-nightly.yaml pass (python3/PyYAML safe_load)
Verify tokenless component contract, positive (current tree) tokenless component contract OK: tokenless provides anolisa-component(tokenless), exit 0
Guard, negative: Provides: line removed from processed spec fails fast: ERROR: tokenless spec must provide anolisa-component(tokenless), exit 1
Guard, negative: component renamed to tokenlessx in archived component.toml.in fails fast: ERROR: tokenless identity mismatch: RPM name 'tokenless', component name 'tokenlessx', exit 1
Guard, negative: .anolisa/component.toml.in deleted from archive fails fast: ERROR: component contract template (.anolisa/component.toml.in) not found in source archive, exit 1
Collect RPM artifacts capability check, positive (freshly built tokenless RPM) Verifying tokenless RPM capabilities: .../tokenless-0.7.13-1.al8.x86_64.rpm, exit 0
Capability check, negative (minimal dummy RPM without the capability) fails: ERROR: ... does not provide anolisa-component(tokenless) and prints actual provides, exit 1

CI at f359ab9: green, no failed checks (checks for other components are skipped by design on this PR).

Risk and compatibility

  • Build/packaging behavior changed (new fail-fast guards)

  • The guards only add pre-build and post-build assertions; they do not alter the spec, tarball layout, or rpmbuild invocation. Builds from a correct tree behave exactly as before. No runtime or user-facing behavior changes.

  • The workflow guards are gated on inputs.component == 'tokenless': RPM builds for the other components (copilot-shell, cosh-ng, agent-sec-core, agentsight, os-skills, ws-ckpt, agent-memory, skillfs, anolisa) run through unchanged code paths.

  • The collect-step check can only fail a build whose built RPM lacks the declared capability — exactly the defect this PR exists to stop shipping ([tokenless] bug: released 0.7.12 RPM still missing Provides: anolisa-component(tokenless) despite fix #2576 on main #2836).

Not run

  • The full Rust test suite (cargo test) was not re-run here because the change touches only the shell build guard and CI workflow YAML, not Rust sources.
  • The GitHub-hosted nightly pipeline (docker-nightly.yaml) was not triggered end-to-end as part of this validation; the new steps were validated by running them verbatim against locally reproduced nightly inputs (source archive, processed spec, built RPM) as detailed above.

…ides

Mirror the build_cosh_ng component-contract guard for build_tokenless:
derive the component name from .anolisa/component.toml.in, verify it
matches the RPM package name, and require an exact
"Provides: anolisa-component(<name>)" line in tokenless.spec.in before
running rpmbuild. Spec drift now fails the build instead of shipping an
RPM that silently lacks the capability used by `anolisa install
tokenless` when the component index is unavailable (alibabaGH-2836).

Signed-off-by: 林生 <linyan.lin@alibaba-inc.com>
@Forrest-ly
Forrest-ly requested a review from samchu-zsl as a code owner August 26, 2026 01:35
@github-actions github-actions Bot added the scope:scripts ./scripts/ label Aug 26, 2026

@qoderai qoderai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本次审查范围内未发现需要修改的问题。


🤖 Generated by QoderView workflow run

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b6181ff416

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread scripts/rpm-build.sh
Comment on lines +493 to +495
if ! grep -Fqx "Provides: anolisa-component(${component_name})" "$spec_in"; then
err "tokenless spec must provide anolisa-component(${component_name})"
return 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce the guard in the RPM-producing workflow

When tokenless RPMs are produced by the checked-in nightly pipeline, this guard never runs: .github/workflows/docker-nightly.yaml delegates the tokenless job to _rpm-build.yaml, which processes the archived spec and invokes rpmbuild directly. Consequently, removing the Provides line still lets that pipeline publish an RPM with the original defect; move or duplicate this assertion in _rpm-build.yaml (ideally verify the built RPM's capabilities) so the production artifact path is protected.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — accepted. Verified the gap: docker-nightly.yaml delegates the rpm-tokenless job to _rpm-build.yaml, which processes the archived spec and invokes rpmbuild directly, so the guard in scripts/rpm-build.sh never runs on the nightly path.

Fixed in f359ab9 by duplicating the assertion into _rpm-build.yaml (gated on inputs.component == 'tokenless', other components unaffected) and adding the artifact capability verification:

  1. New Verify tokenless component contract step before Build RPM: derives the component name from .anolisa/component.toml.in in the source archive, verifies it matches the RPM package name, and requires the exact Provides: anolisa-component(<name>) line in the processed spec — same assertions as build_tokenless.
  2. Collect RPM artifacts now verifies each built RPM actually publishes the capability via rpm -qp --provides, catching a malformed Provides line that rpmbuild would silently drop (mirrors the existing agentsight verification hook).

Local verification: simulated the nightly spec processing with the real tokenless.spec.in + component.toml.in — happy path passes; removing the Provides line (the original defect scenario), a Name/component mismatch, and a missing contract template all fail the guard; built minimal test RPMs with/without the capability to confirm the artifact check accepts/rejects correctly; actionlint clean. CI re-runs on this push.

The checked-in nightly pipeline produces tokenless RPMs through
docker-nightly.yaml -> _rpm-build.yaml, which processes the archived
spec and calls rpmbuild directly, so the build_tokenless guard added
to scripts/rpm-build.sh never runs there: deleting the
"Provides: anolisa-component(tokenless)" line would still let the
nightly publish an RPM with the original defect (alibabaGH-2836).

Close the gap with the same component contract assertion, gated on
inputs.component == 'tokenless' so other components are unaffected:

- New "Verify tokenless component contract" step before rpmbuild:
  derive the component name from .anolisa/component.toml.in in the
  source archive, verify it matches the RPM package name, and require
  an exact "Provides: anolisa-component(<name>)" line in the
  processed spec.
- Extend "Collect RPM artifacts" to verify every built RPM actually
  publishes the anolisa-component(<name>) capability via
  rpm -qp --provides, catching malformed Provides lines that rpmbuild
  would silently drop.

Signed-off-by: 林生 <linyan.lin@alibaba-inc.com>

@kongche-jbw kongche-jbw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review baseline: 83781b482182...f359ab95d291

[P2] 更新 PR 描述以覆盖 nightly workflow 变更

.github/workflows/_rpm-build.yaml:252 起已经加入 nightly 构建前检查和成品 RPM
能力校验,但 PR 正文仍称最终仅修改 scripts/rpm-build.sh,验证表也只覆盖首个提交。
这会让后续审查者无法从 PR 正文复现当前范围与风险。建议同步更新 What changed、
Validation 和 Risk,记录 f359ab9 中新增路径的实际验证结果。

@Forrest-ly

Copy link
Copy Markdown
Collaborator Author

@kongche-jbw 感谢 review,意见合理,已采纳:PR 描述已更新,完整覆盖 f359ab9 的 nightly workflow 变更。

What changed:拆分为两个 commit 小节 —— b6181ffscripts/rpm-build.shbuild_tokenless 守卫)与 f359ab9_rpm-build.yaml 中新增的 Verify tokenless component contract 步骤 + Collect RPM artifacts 的成品 RPM 能力校验,按 inputs.component == 'tokenless' 门控),并补充了 archive 布局说明(package-source 产物同时包含 component.toml.in 模板与生成的 component.toml,guard 的 find 只匹配 .in 模板)。

Validation:保留原有针对首个提交的实测表,并新增 f359ab9 新增路径的实际验证结果。由于 nightly 路径只在 CI 中执行,验证方式为:本地忠实复刻 nightly 输入(按 package-source 流程生成源码归档、按 Prepare source and spec 原样处理出 tokenless.spec),然后逐字提取 workflow 中的新增步骤脚本(仅替换 ${{ inputs.* }})实际运行:

场景 结果
YAML 语法(_rpm-build.yamldocker-nightly.yaml python3/PyYAML 解析通过
guard 正向(当前树) tokenless component contract OK,exit 0
guard 负向:删除处理后 spec 的 Provides: ERROR: tokenless spec must provide anolisa-component(tokenless),exit 1
guard 负向:归档内组件名改为 tokenlessx ERROR: tokenless identity mismatch: RPM name 'tokenless', component name 'tokenlessx',exit 1
guard 负向:归档中删除 .anolisa/component.toml.in ERROR: component contract template ... not found in source archive,exit 1
成品校验正向(最终树重新构建的 tokenless-0.7.13-1.al8.x86_64.rpmscripts/rpm-build.sh tokenless exit 0) 校验通过,exit 0
成品校验负向(无该 capability 的 dummy RPM) ERROR: ... does not provide anolisa-component(tokenless),exit 1

Risk:已更新,注明两处守卫均为新增断言、不改变 spec/归档/rpmbuild 调用,workflow 守卫按 inputs.component == 'tokenless' 门控、其余组件构建路径不变。

CI 在 f359ab9 上无失败项。请重新 review。

@kongche-jbw kongche-jbw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review baseline: 83781b482182...f359ab95d291

未发现阻塞问题。

Remaining risks:

  • 本轮未触发 GitHub-hosted nightly 端到端构建;当前环境也没有 rpm/rpmbuild,
    因此未独立重建并查询成品 RPM。

Verification scope:

  • 复核完整 diff、归档与 nightly 调用链、全部 PR 评论、Review 和 reviewThreads。
  • git diff --checkbash -n scripts/rpm-build.sh、两份 workflow 的 PyYAML 解析通过。
  • 当前 head SHA 上远端检查无失败项;组件测试按本次变更范围跳过。

@ikunkun-sys

Copy link
Copy Markdown
Collaborator

Closing because the internal RPM release pipeline does not use either scripts/rpm-build.sh or .github/workflows/_rpm-build.yaml. The repository and tokenless/v0.7.12 tag already contain Provides: anolisa-component(tokenless), so this PR does not change the path that produced the affected artifact. The release-side spec will be corrected in the internal publishing process. Keeping #2836 open until a corrected RPM is published and verified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope:scripts ./scripts/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[tokenless] bug: released 0.7.12 RPM still missing Provides: anolisa-component(tokenless) despite fix #2576 on main

3 participants