Skip to content

Commit e9d2c51

Browse files
committed
2026.9.6.6 —— 一个包一个版本,规则自带它的环境
版本在一个地方属于包的身份,在另一个地方不属于。条件合并按包去重 (`xim:glibc` 与 `xim:glibc@2.40` 是一个条目),而跨包的划分比对整个地址 串(是两个包)。于是工程钉 `xim:cuda-nvcc@13.3.33`、规则包钉 `@>=12.9.86` 时两份都装 —— 每份数 GB —— 而 `fillXpkgDirs` 里「同名保留第 一个值」让 `xpkg_dir` 只答其中一个。装了两份、用了一份,没有一句话提到它。 身份统一为 `(namespace, name)`,版本永远是这个包上的约束。装哪一版分两 步:裁决 —— 离产物更近的声明赢,不带版本的声明弃权,结果被报出来;校验 —— 赢家必须满足每一条落败的要求,不满足就拒绝并同时点出两侧与出路。裸版 本是选择不是要求,两条不同的精确钉走裁决而不被拒绝,否则每一个「依赖钉了 工具、工程也钉了」的组合会在升级当天变成硬失败。 校验是一次比较不是一次搜索:版本由裁决选定再被检查,所以引擎从不需要问索 引「有哪些版本」,也就不带约束求解器。代价写进文档而不是藏起来。 `mcpp::xpkg_dir` 现在回答范围。版本位一直接受范围表达式且 xlings 真的求解 它,而这个查询把整个位置当目录名比对 —— 于是 `>=8.5.0` 装上了载荷然后回答 「没装」。这正是让规则包无法声明下界的那道缝。 四处新拒绝有了名字:`device-source-unconsumed`、`accel-backend-undeclared`、 `host-module-missing`、`tool-version-conflict`。 xlings pin 从 2026.8.30.2 抬到 2026.9.5.1。 判据:e2e 627(装了什么与答了什么必须同时断言)、628(拒绝 + 抬钉后通过的 反向腿 + `--format json` 的 token)、629(范围被安装并被回答)、630(两重门 的两条腿);单测 test_xlings_address_set 与 xpkg_payload_at 的范围/不可解析 版本两组。三条 e2e 在已发布的 2026.9.6.5 上实测为红。 规范:SPEC-001 §10、SPEC-004 §4.5 与判据 5–7。
1 parent 923de18 commit e9d2c51

35 files changed

Lines changed: 1880 additions & 94 deletions
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# 一个包一个版本:xlings 地址的身份,以及 2026.9.6.5 之后的文档对齐
2+
3+
> 状态:设计,未实现。本文的每一条「现状」都标注了它是****出来的还是****出来的。
4+
> 伴随文档:`2026-09-07-general-build-infrastructure-gaps-design.md`(§15 记录了本轮
5+
> 五处缺口),本文处理它遗留的第六处,以及随之而来的文档与生态对齐。
6+
7+
## 0. 这份方案要解决的一句话
8+
9+
**版本在一个地方属于包的身份,在另一个地方不属于。** 于是同一个包被两处以不同版本声明
10+
时,系统认为那是两个包,把两份都装下来。
11+
12+
## 1. 现状:版本语义已经在了,缺的是身份的一致
13+
14+
### 1.1 版本语义已经可用(**实测**,两个方向)
15+
16+
`[xlings.workspace]` 的版本位接受范围表达式,并且**真的被求解**:
17+
18+
| manifest | 读数 |
19+
|---|---|
20+
| `"xim:shaderc" = ">=2026.1"` | `Provisioning [xlings.workspace] entries (xim:shaderc@>=2026.1)`,构建通过 |
21+
| `"xim:shaderc" = ">=2099.1"` | 被拒绝:`package 'xim:shaderc@>=2099.1' not found in the synced index` |
22+
23+
反向那条是判据的关键:只跑正向,一个把范围当字面量放过去的实现同样会「通过」。
24+
25+
索引侧也早在用同一套写法 —— `xim:libX11@>=1.8``xim:glibc@>=2.38` 出现在多个 recipe
26+
`deps` 里。
27+
28+
**结论:不需要引入版本语义。** 「钉具体版本还是钉范围」已经是作者的选择。
29+
30+
### 1.2 但身份有两套定义(****代码)
31+
32+
| 站点 | 身份是什么 | 冲突时 |
33+
|---|---|---|
34+
| `merge_conditional_config`(prepare.cppm:264) | `package_of()``(ns, name)`,**不含版本** | 更具体的赢,并发 `xlings/axis-override` 告警说明用了哪条 |
35+
| `graph_xlings_split` | `find(rootSpecs, spec)`**整个地址串** | 不同串 = 不同包,两份都进供给列表 |
36+
37+
于是工程钉 `xim:cuda-nvcc@13.3.33`、规则包钉 `@12.9.86` 时,两份都装 —— 每份 2–3 GB。
38+
`fillXpkgDirs` 里「同名保留第一个值」的规则让 `xpkg_dir` 答工程那份,所以**装了两份、
39+
用了一份**,且没有任何一句话提到这件事。
40+
41+
正确的那套语义已经写好了,只是没有用在第二个站点上。
42+
43+
## 2. 修法:一条规则,两条配套,不需要求解器
44+
45+
### 2.1 规则
46+
47+
> **包的身份是 `(namespace, name)`。版本永远是**约束**,不是身份的一部分。**
48+
49+
这一条同时给出两件被要求的性质:
50+
51+
- 「所有地方都支持版本语义」—— 因为不再有第二种身份,就没有第二处需要单独支持;
52+
- 「钉具体版本还是钉范围由开发者选」—— 因为两者都只是约束,系统不区分。
53+
54+
**减少**机制:今天有两套身份定义,统一后剩一套。
55+
56+
### 2.2 裁决:离消费者更近的赢,并且说出来
57+
58+
同一身份上有多条声明时,**离消费者更近的那条赢**:工程 > 依赖。同一 manifest 内则是
59+
**更具体的赢**:`[target.<selector>]` > 顶层。
60+
61+
这是两条不同的序,不该用一个词盖住:「更具体」说的是谓词的窄窄,「更近」说的是声明者
62+
与最终产物的距离。后者是新的一条,前者 `merge_conditional_config` 已经在做,并且已经有
63+
`xlings/axis-override` 负责「说出来」。跨包这一趟复用同一条告警。
64+
65+
**两个依赖互相冲突**(规则 A 要 `>=8.5`、规则 B 要 `<8.5`,工程什么都没写)时没有「更近」
66+
可言,那种情形直接走 §2.3 的拒绝,消息点出两个包各自的约束。
67+
68+
### 2.3 校验:赢家必须满足其余每一条约束
69+
70+
这是**唯一新增**的一条,也是让「不需要求解器」成立的那条。
71+
72+
选版本不需要求交 —— 裁决说了算。求交只在「赢家违反了输家的约束」时才有意义,而那种情形
73+
正确的动作是**拒绝并点名两边**,不是悄悄选一个:
74+
75+
```
76+
error: `xim:cann-toolkit` is pinned to 8.3.RC1 by this project, and
77+
`mcpp:plugins` (feature `rules-ascendc`) requires >=8.5.0.
78+
fix: raise the pin, or drop it and let the rule's constraint decide.
79+
```
80+
81+
所以是「验证一个已选定的版本」,不是「在约束集合里搜索」。前者是一次比较,后者要知道
82+
索引里有哪些版本可选。
83+
84+
### 2.3.1 这条捷径的已知代价,不能不写
85+
86+
不求交意味着**系统会拒绝一些求解器本可以满足的组合**。工程写 `>=8.0`、规则写 `8.5.0`,
87+
而索引里最新是 8.3:裁决让工程赢,`>=8.0` 解析到 8.3,校验发现它不满足规则的 `8.5.0`,
88+
于是拒绝 —— 尽管 8.5.0 本身同时满足两边。
89+
90+
这是有意接受的代价,理由有三条:拒绝的消息里已经写着确切的出路(「抬 pin,或者去掉 pin
91+
让规则的约束决定」);求解器要引入「可选版本集合」这个此处还不存在的输入;而这种组合
92+
(一边范围、一边精确、且交集不在范围的最大值上)在实践中是少数。
93+
94+
**如果它变成多数,那就是引入求交的信号** —— 而不是现在。
95+
96+
### 2.4 为什么这比「按包去重」更准确
97+
98+
我在讨论中先把出路列成三选一(不钉版本 / 引擎按包去重 / 维持现状)。**那个划分是错的**:
99+
身份统一之后,「不钉版本」只是约束的一种取值,不需要单独成为一条路。三条塌缩成一条。
100+
101+
## 3. 影响面:三个站点必须一起改
102+
103+
单独改 `graph_xlings_split` 会造出本轮 §15.5 那种形状的缺陷 —— 装的是 A,`xpkg_dir`
104+
答的是 B。三处共同定义了「哪个版本被安装、哪个版本被回答」:
105+
106+
1. `graph_xlings_split` —— 去重与 root/graph 的划分
107+
2. `fillXpkgDirs` —— 「同名保留第一个值」,决定 `xpkg_dir` 答谁
108+
3. `provision_xlings_addresses` —— 实际收到的地址列表
109+
110+
判据必须同时观察「装了什么」和「答了什么」,只看其中一个会漏掉这类缺陷。
111+
112+
## 4. 判据
113+
114+
| # | 构造 | 断言 | 今天 |
115+
|---|---|---|---|
116+
| C1 | 工程与其规则包钉同一包的**不同版本** | store 里只出现**一个**版本目录 ||
117+
| C2 | 同上 | `xpkg_dir` 答的就是那个目录 | 绿(但与 C1 一起看才有意义) |
118+
| C3 | 同上 | 输出里有一句说明谁赢了 ||
119+
| C4 | 工程钉的版本**不满足**规则的约束 | 拒绝,消息同时点出两边与各自的约束 ||
120+
| C5 | 只有规则声明(工程什么都不写) | 装规则要求的版本,构建通过 | 需实测 |
121+
| C6 | 范围不可满足 | 拒绝 | 绿(§1.1 已测) |
122+
| C7 | 工程只写 `[build-dependencies]` 那一行,不写任何 `[xlings.workspace]` | 规则声明的 toolkit 被装上,构建通过 | 需实测(§6.1) |
123+
| C8 | 同上,再加工程自己的钉 | 只装工程钉的那一版,且构建通过 | 红(即 C1,带真实 payload) |
124+
125+
C1 与 C4 是这份方案存在的理由;C6 是既有行为,列出来是为了防止改动把它弄坏。
126+
127+
## 5. 文档对齐:实测出来的清单
128+
129+
以下每一条都用 grep 在树上核过,不是回忆。
130+
131+
### 5.1 明确过期,必须改
132+
133+
| 文件 | 问题 |
134+
|---|---|
135+
| `docs/specs/manifest-semantics.md` §4.3.1 | 仍写「`<selector>` **禁止**命名五个目标侧层(`accelerator``c-abi`…)」。2026.9.6.5 起 `accelerator` **被接受**。且该句自身不自洽:说「五个」而括号里列了六个 |
136+
| `docs/11-machine-output.md` | 本轮三处新拒绝(设备源无 action、未声明的后端、缺 host module)**都没有 refusal code** —— 实测 `refusal::record` 在三处附近均零次出现,而 `build_program.cppm` **已经 import 了 `mcpp.build.refusal`**,所以这是遗漏不是能力缺失。机器消费者分不开它们,而这份文档正是拒绝词表的规范 |
137+
| `examples/09-heterogeneous/README.md` | 表格只列四个目录,`multi-backend/``cann/` 缺席;结尾「Start with `cuda/`. The other three assume it.」在六个目录下已不成立 |
138+
139+
### 5.2 本轮已改,列出以便复查
140+
141+
`docs/05-mcpp-toml.md` / zh(`exports``accelerator` 谓词键、accel 门控 xlings 与
142+
dependencies、build-dependencies 的更正)、`docs/07-build-mcpp.md` / zh(`link-flag`
143+
设备源必须到达 action、规则只取自己认领的扩展名、未提供的 import 被点名拒绝)、
144+
`docs/20-heterogeneous-builds.md` / zh(`accelerator = "none"` 进词表、CPU 回退改用
145+
`none``.asc`/`.cce` 进扩展名表、rules-ascendc 进 lane 表、四条 lane → 五条)。
146+
147+
### 5.3 不需要改
148+
149+
`docs/14-target-side.md` 的「五个层」指的就是被解析的那五个,从来不含 `accelerator` ——
150+
与本轮的日程划分**恰好一致**。带 `(2026.9.6.x+)` 的行是历史标记,保持原样。
151+
152+
## 6. 生态侧:每个规则自带它的环境
153+
154+
### 6.1 规则拥有默认,工程拥有例外
155+
156+
这是本方案在用户侧的**主要**收益,比 §1.2 的「装两份」更常被碰到。
157+
158+
今天一个要编 CUDA 核的工程写两块:一条 `[build-dependencies]` 边选规则,再加四行
159+
`[xlings.workspace]` 把 toolkit、cudart、libcurand、cccl 各自钉一遍。第二块是**规则
160+
已经知道的事**——哪个包、最低哪一版,由写规则的人决定,而不是由用它的人重复。
161+
162+
改成:
163+
164+
```toml
165+
# rules/cuda.cppm 所在的包,mcpp-plugins
166+
[target.'cfg(accelerator = "cuda")'.feature-xlings.rules-cuda]
167+
"xim:cuda-nvcc" = ">=12.9.86"
168+
"xim:cuda-cudart" = ">=12.9.79"
169+
"xim:libcurand" = ">=10.3.10.19"
170+
"xim:cuda-cccl" = ">=12.9.27"
171+
```
172+
173+
两重门:feature 说「要不要这个规则」,selector 说「哪些构建真的下载」。CPU-only 构建
174+
两道门都不过,一个字节都不装。
175+
176+
于是工程侧只剩一行:
177+
178+
```toml
179+
[build-dependencies.mcpp]
180+
plugins = { version = "0.2.4", features = ["rules-cuda"], host-module = true }
181+
```
182+
183+
五个规则一起改,不留一个例外:`rules-cuda``rules-hip``rules-sycl``rules-spirv`
184+
`rules-ascendc`**前一稿写「CUDA 暂不动」是错的** —— 留一个例外就等于告诉用户「有时要
185+
自己写、有时不要」,而「什么时候要」没有任何地方说得清。理由那一稿写的是「12.9 与 13.x
186+
耦合驱动下界,那个决定属于工程」;可决定属于工程**不等于**默认属于工程 —— 下界写成
187+
`>=12.9.86` 就把「至少要这么新」交给规则,把「具体哪一版」留给工程,两件事各归各位。
188+
189+
### 6.2 例外怎么写,以及为什么它现在才安全
190+
191+
工程仍然可以钉:
192+
193+
```toml
194+
[target.'cfg(accelerator = "cuda")'.xlings.workspace]
195+
"xim:cuda-nvcc" = "13.3.33"
196+
```
197+
198+
**这条覆盖之所以能用,正是 §2 的裁决与校验。** 没有身份统一,它不是覆盖而是第二份安装:
199+
`xim:cuda-nvcc@13.3.33``xim:cuda-nvcc@>=12.9.86` 是两个串、两条记录、两份 2 GB 的
200+
payload,而 `xpkg_dir` 只答其中一个。所以 §6 不是 §2 的下游应用,它是 §2 **成立的判据**
201+
——一个用户会走的、今天会坏的路径。
202+
203+
顺序因此是固定的:引擎先落地,插件再发。反过来做,插件的默认与工程的钉一起装两份。
204+
205+
### 6.3 文档要说的一句话
206+
207+
`docs/20``docs/05` 各加一段,说清三件事:默认由规则带,不需要写;要换版本就在工程里
208+
写同名条目,离消费者近的赢;赢家不满足规则的下界时构建被拒绝并点名两边。
209+
210+
### 6.4 examples
211+
212+
- `cann/app``cuda/``sycl/``hip/``vulkan/`:删掉各自的 `[xlings.workspace]`
213+
加速器块。这是最直接的读数——**示例的行数就是用户要写的行数**
214+
- `multi-backend`:**保留** `xim:cuda-nvcc = "12.9.86"` 一行,并把注释改成「这是覆盖
215+
的示范」。整个生态需要恰好一个地方示范例外路径,多一个都是噪声。
216+
- `09-heterogeneous/README.md`:补 `multi-backend/``cann/` 两行,改结尾那句。
217+
218+
### 6.5 索引
219+
220+
无改动。`xim:cann-toolkit` 与 CUDA/SYCL 各包都已发布;规则包改用 feature-xlings 只需
221+
plugins 的一次小版本。
222+
223+
## 7. mcpp 依赖的 xlings pin
224+
225+
`src/xlings/xlings.cppm``pinned::kXlingsVersion``2026.8.30.2` 抬到
226+
`2026.9.5.1`(当前最新)。这个常量是 `.github/tools/check_version_pins.sh`**唯一
227+
真源**:该脚本把 `.github/` 下每一处 xlings 版本与它比对,不等就红。所以这一处改动是
228+
一个常量加脚本枚举出来的那几处工作流,不是一次搜索替换 —— 判据是脚本本身通过。
229+
230+
它与本方案的关系是直接的:`[xlings.workspace]` 的范围求解由 xlings 侧执行,而 §2 的
231+
校验建立在「范围真的被求解」之上(§1.1 的两个方向就是在验这件事)。停在三个月前的
232+
pin 让这条依赖变成一个没人核过的假设。
233+
234+
## 8. 分期与依赖
235+
236+
|| 内容 | 依赖 |
237+
|---|---|---|
238+
|| §5.1 三处文档 + 三处新拒绝补 refusal code + §7 的 pin ||
239+
|| §2 的身份统一(三个站点)+ C1/C3/C4/C5 | 一期的 refusal code(C4 要一个码) |
240+
|| §6.1 五个规则自带环境 + §6.4 示例瘦身 | 二期**必须先发布** |
241+
242+
三期跨仓库且顺序不可交换:插件的默认要靠引擎的裁决才不会变成第二份安装。
243+
244+
## 9. 自我 review:讨论过程中被推翻的四处判断
245+
246+
| 我先说的 | 为什么错 |
247+
|---|---|
248+
| 「要不要引入版本语义」 | 语义已经在,实测两个方向。问题从头就不是这个 |
249+
| 出路是三选一(不钉版本 / 按包去重 / 维持现状) | 身份统一之后三条塌缩成一条:「不钉版本」只是约束的一种取值 |
250+
| 需要一个版本求解器 | 过重。选版本由裁决决定,求交只在**校验**时需要,而校验是一次比较不是搜索 |
251+
| 「CUDA 暂不动,那个决定属于工程」 | 混淆了**决定权****默认值**。下界属于规则、具体版本属于工程,两者不冲突;留一个例外反而让「什么时候要自己写」无处可查(§6.1) |
252+
253+
前三处有同一个形状:**在没有把已有机制查清楚之前就开始设计新机制。** §1.1 那两行实测
254+
是十几秒的事,而它把整份方案的规模从「引入约束求解」缩到「统一一处身份定义」。
255+
256+
第四处形状不同:**我把「这里有真实的复杂度」读成了「这里应该保持现状」。** 12.9 与
257+
13.x 的驱动下界差异是真的,但它论证的是「工程要能覆盖」,而我拿它论证了「规则不该有
258+
默认」——同一个事实支持的是相反的结论。

.github/actions/bootstrap-mcpp/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ inputs:
2525
# `package.name`, so one of the two was simply unreachable — and which one
2626
# depended on the machine, which is why CI failed on `compat:lua` on
2727
# Windows and `mcpplibs.capi:lua` on Linux. Never pin below that.
28-
default: '2026.8.30.2'
28+
default: '2026.9.5.1'
2929
cache-target:
3030
description: also restore/save target/ (build artifacts + BMIs)
3131
required: false

.github/actions/setup-macos-llvm/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ inputs:
1515
# Floor imposed by the index, not a routine bump — see
1616
# .github/actions/bootstrap-mcpp/action.yml for why 0.4.69 is required
1717
# (two packages named `lua` in one repo need openxlings/xlings#381).
18-
default: '2026.8.30.2'
18+
default: '2026.9.5.1'
1919

2020
runs:
2121
using: composite

.github/workflows/bootstrap-macos.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
# Dormant (workflow_dispatch only), but kept in step with the rest —
1818
# check_version_pins.sh holds it there. Floor: 0.4.69, below which the
1919
# index cannot resolve two packages that share a short name.
20-
XLINGS_VERSION: '2026.8.30.2'
20+
XLINGS_VERSION: '2026.9.5.1'
2121
steps:
2222
- uses: actions/checkout@v4
2323

.github/workflows/ci-fresh-install.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ jobs:
152152
env:
153153
XLINGS_NON_INTERACTIVE: '1'
154154
run: |
155-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.8.30.2
155+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.5.1
156156
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
157157
158158
- name: Install mcpp and config mirror
@@ -293,7 +293,7 @@ jobs:
293293

294294
- name: Install xlings + mcpp
295295
run: |
296-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.8.30.2
296+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.5.1
297297
# Deliberately NOT writing to $GITHUB_PATH here. On container
298298
# images that declare no PATH in their config (opensuse/
299299
# tumbleweed), appending a single dir to GITHUB_PATH makes the
@@ -364,7 +364,7 @@ jobs:
364364
# (older ones carry minos=15 and refuse to start).
365365
# v0.4.51+: in-process sha256 — this image has no sha256sum
366366
# binary, so pinned fetches failed before it.
367-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.8.30.2
367+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.5.1
368368
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
369369
370370
- name: Install mcpp and config mirror

.github/workflows/ci-linux-e2e.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ jobs:
282282
283283
- name: Bootstrap xlings + released mcpp
284284
run: |
285-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.8.30.2
285+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.5.1
286286
export PATH="$HOME/.xlings/subos/current/bin:$PATH"
287287
xlings update
288288
xlings install mcpp -y -g

.github/workflows/cross-build-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ jobs:
122122
# release assets were uploaded in a broken state (records present,
123123
# blobs missing → 404 on GET); re-uploaded clean. The stale-INDEX
124124
# half is handled by the marker-clear below.
125-
XLINGS_VERSION: '2026.8.30.2'
125+
XLINGS_VERSION: '2026.9.5.1'
126126
run: |
127127
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
128128
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \
@@ -263,7 +263,7 @@ jobs:
263263
- name: Bootstrap mcpp via xlings
264264
env:
265265
XLINGS_NON_INTERACTIVE: '1'
266-
XLINGS_VERSION: '2026.8.30.2'
266+
XLINGS_VERSION: '2026.9.5.1'
267267
run: |
268268
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
269269
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \

0 commit comments

Comments
 (0)