huawei-cloud-publish-work-to-gallery

v2026.09.24

Publish user's work to the Huawei Cloud University Operations Platform (华为云高校运营平台/作品陈列馆). Use this skill whenever the user wants to publish, submit, or upload a project/work to the gallery or a training camp (训练营) on the platform — including casual phrasings like "把作品发布上去", "投稿到陈列馆", "传作品到平台", "提交作品/项目", "报名发布作品", as well as formal ones like "publish to work gallery", "submit to training camp", "upload work to the platform". Do NOT use for general dev questions, git push to GitCode alone, or platform browsing without publishing intent.

GitHub
Install command
npx skhub add huaweicloud/huawei-cloud-publish-work-to-gallery
Markdown
SKILL.md

Publish Work to Gallery

发布作品至华为云高校运营平台。确定性子任务优先调用内置脚本(单入口、fail-fast、自带 --help),stdout/退出码即判定依据。脚本报错才查 references/troubleshooting.md。

Pipeline

Step 1 (workDir, domainID, STS)
Step 2 (port→变量, envUrl→变量)              ← 依赖 Step 1
  ├── Step 3 (gitUrl, gitBranch, workName)   ← 只依赖 workDir
  ├── Step 5 (introduction, camps)           ← 只依赖 workDir + STS
  ├── Step 4 (coverImage)                    ← 依赖 port + workName
  └── Step 6 (detailZip)                     ← 依赖 workName + 代码分析
Step 7 (trainingCampId)                      ← 依赖 Step 5 camps
Step 8 (publish)                             ← 依赖以上全部

并行(Step 2 完成后):Step 3/4/5/6 互不依赖,四者全并行(取最长路径 Step 4 ~90s,而非串行 ~160s)。Step 4 内 preflight + ensure-utf8 再并行。

变量贯穿:port/workName/envUrl 在最早步骤确定后作为变量传递全流程,禁止硬编码(隧道 URL 含 port,换端口时 envUrl 随之变)。

执行模型:① 脚本契约优先——按 stdout 成功信号判定,成功路径零源码读取;失败才 脚本提示 → troubleshooting 对应节 → grep 脚本源码 逐级查 ② 禁止手工绕过门禁(publish-work.mjs 内置 verifyGates() 复核)③ 网络超时统一 3s ④ detect-env.mjs 确定平台后只读对应平台 reference(按目录跳转,不全读)⑤ 合并无依赖的 bash 调用:用 ; 串联进一条命令,减少工具往返(每次 ~1-2s)。

脚本契约速查

步骤脚本/命令成功信号(exit 0 且)失败(exit 1;2=参数错)
前置api.mjs GET /v1/gallery/announcements/current --prefix open-api-gueststdout 首行 #status=200超时/拒连 → 提示排查网络
前置node <skill>/scripts/check-version.mjs(自动读自身 version + 请求远端版本,内部解析,stdout 仅状态行)exit 0 且首行 status=ok/status=skipexit 1(首行 status=outdated + 平台下发升级文案)→ 原样提示用户升级,停止发布
5/7api.mjs GET "/v1/gallery/camps" --creds-file <json> --fields "id,name,school,status,startsAt,endsAt"#status=200(--fields 投影减 token)401 → 刷新 STS
1scan-projects.mjsstdout #project <n> <path> <type>exit 1=无候选
1resolve-domain.mjs [--hcloud <exe>]stdout #domain=<id> name=<name>exit 1=hcloud 失败(stderr 含排查指引)
1gen_sts.py --account <id>写 sts-creds.json(含 _refresh)+sts-creds.sh见 [troubleshooting#domain-id-resolution-issues]
3strip-git-credential.mjs "<rawUrl>"stdout=安全 URL(https:// 开头、.git 结尾、无 @)@/非 https/非 .git → 停止发布
3ensure-gitcode-credential.mjs#credential=found 或 #credential=missing(exit 0)exit 1=Windows 无凭证且 skill 未装(stderr 含安装命令)
3extract-workname.mjs <workDir>stdout #name=<name> source=<来源>exit 1=workDir 不存在
4preflight.sh / preflight.ps1写 font-gate-ok(ok=true gate=preflight)截图/封面/图表禁止
4ensure-utf8.mjs <dir>写 utf8-gate-ok编码非 UTF-8 → 禁止截图
4build-cover.mjs --url … --project-dir … --title … --out …stdout 一行 #cover=… layout=… multi=…exit 1 → 截图/校验/合成任一失败,stderr 详情
4screenshot_guard.py http://… --out <png> --quiet写 screenshot-gate-ok + 出 PNG字形/字符集不过 → 修字体重试
4generate_cover.py --screenshot … --title … --out …封面 PNG,再过 verify-glyphs.pyexit 1 → 禁止继续合成
4/6verify-glyphs.py <img> --quietexit 0(stdout 仅 1 行省 token)exit 1 → 疑似豆腐块 → 修字体
5count-cjk.mjs --file <utf8.txt>总字符数 15~50exit 1 → 改写简介再计
6generate_diagram.py --html … --out …图表 PNG,再过 verify-glyphs.py --quiet同封面
6build-detail-zip.mjs --readme <md> --resources <dir> --out <zip>打包+校验一步完成exit 1 → 按输出修复重打
8check-gates.mjs --cover <png> --detail <zip> --strict --max-age 3600 --quietexit 0(stdout 仅 1 行省 token)exit 1 → 回退重跑门禁
8publish-work.mjs <utf8-params.json>#status=201(仅输出 workId/workUrl/reward)409/其他;失败时原样输出完整响应

标记文件位置:Linux /tmp/;Windows os.tmpdir()(%TEMP%)。

前置锁定

  • hcloud + AK/SK:Step 1 需要。未装/未配置 → troubleshooting#domain-id-resolution-issues。
  • git:Step 3;zip:Step 6(Linux yum install zip;Windows 用 .NET ZipFile)。Windows 首次见 windows-setup.md。
  • 连通性:api.mjs GET "/v1/gallery/announcements/current" --prefix open-api-guest,连通 OK 即可继续。
  • 版本检查(尽力而为):node <skill>/scripts/check-version.mjs——脚本自动读本文件 frontmatter version: 并请求平台版本接口比较。status=ok/status=skip(非 2xx/解析失败)→ 继续,不阻塞;status=outdated → 将脚本输出的升级文案原样告知用户并停止发布(连同行公告接口一起两条命令可并行/串联合并执行,减少工具往返)。

Core Workflow

Step 1: Select Work Directory & Resolve IAM Domain Info

  1. 告知用户(选目录=同意):将创建 IAM 自委托 SELF_VERIFY 生成 STS 临时凭证(900s),永久 AK/SK 留本地不上传。
  2. 扫描项目根:node <skill>/scripts/scan-projects.mjs——自动递归 **/README.md,检查指示文件,排除 skills//node_modules//dist/ 等,扫描 CodeArts 沙箱目录。stdout 每行 #project <n> <path> <type>。
  3. 列候选,等用户选 → workDir。
  4. 解析 Domain ID:node <skill>/scripts/resolve-domain.mjs [--hcloud <exe>]——自动 hcloud configure set --region + IAM KeystoneListAuthDomains + 提取 domain_id。stdout #domain=<id> name=<name>。hcloud 不在 PATH 时传 --hcloud。凭证优先级:env → hcloud 已配置 → 引导用户(troubleshooting#2)。
  5. 生成 STS:python <skill>/scripts/gen_sts.py --account <domainID> → sts-creds.json(含 _refresh,使 401 自动刷新)。
  6. 输出:已获取 IAM Domain ID: <id>,用于将作品关联至您的华为云账号。

Output: workDir、domainID、credsFile。

Step 2: Run Project & Open Tunnel

询问是否运行项目+开隧道。拒绝则 envUrl="" → Step 3。

  • 端口清理:netstat -ano | findstr :<port>(Win),残留进程 kill。
  • 启动:优先入口脚本(npm run dev/python main.py);纯前端 npx http-server . -p <port>。≤30s 健康检查。
  • 核对内容:curl -sf --max-time 3 http://localhost:<port> 首 100 字符须匹配本项目(<title>/项目名),Index of //404 → 清进程重启。
  • 隧道:devbridge host -p <port> -e 2,curl -sf --max-time 10 验证。失败不阻塞,置 envUrl=""。详见 devbridge-tunnel.md。

Output: port、envUrl(或 "")。

Step 3: Git Repository Info & Work Name

gitUrl 必填,gitBranch 必须显式读取。workName 从 README 解析/合成(<30 字符)。

  1. git -C <workDir> remote get-url origin + branch --show-current。
  2. 凭证排查:node <skill>/scripts/ensure-gitcode-credential.mjs——自动检测本机 GitCode 凭证(git credential fill/~/.git-credentials/$GITCODE_TOKEN/cmdkey),无凭证时按平台给可行路径(Linux 提示手动配置 / Windows 检测 gitcode-oauth skill 并输出安装命令)。exit 0=有凭证或已有路径;exit 1=Windows 无凭证且 skill 未装(stderr 含安装命令 + Windows Git Bash 兼容提示)。
  3. 凭证剥离:gitUrl="$(node <skill>/scripts/strip-git-credential.mjs "$(git remote get-url origin)")"。硬校验:无 @、https:// 开头、.git 结尾。
  4. 命名:node <skill>/scripts/extract-workname.mjs <workDir>——按优先级 frontmatter → H1 → manifest → index.html <title> → 目录名提取。stdout #name=<name> source=<来源>。source=dirname 时 agent 可合成/修改(<30 字符)。

Output: gitUrl、gitBranch、workName。

Step 4: Cover Image

门禁(并行):

门禁命令标记
渲染preflight.sh(Win: preflight.ps1)font-gate-ok
编码ensure-utf8.mjs <dir>utf8-gate-ok

门禁失败禁止截图/合成。preflight 以标记文件 ok=true 为准(轮询 ≤180s)。Linux 首次运行必须后台化(下载 Chromium ~111MB,前台会被 shell 超时 SIGPIPE 杀死,主进程死后不会写 gate 文件,轮询徒劳);Windows 通常已预装系统浏览器,前台即可。

封面一键生成(内置:页数判定 + 单/多图概率抽样 + 截图 + 合成 + 校验):

node <skill>/scripts/build-cover.mjs \
  --url "http://127.0.0.1:<port>" --project-dir <workDir> \
  --title "<workName>" --tagline "<一句话>" --description "<主体介绍,1~3 句>" \
  --out <coverImagePath>
  • 布局决策在脚本内部闭环(agent 无感知):单页项目只用 7 个单图布局;多页项目(.html 数 ≥2)额外加入 3 个多图布局(大图+小图拼贴),统一概率池等概率抽样,多页时多图出现概率 3/10。
  • 多图布局会截首页 + 候选页(最多 3 张小图);候选页截图失败自动跳过,最少保底 1 张。
  • stdout 仅输出一行结果:#cover=… layout=… multi=yes|no pages=<n> scheme=…;日志走 stderr。失败 exit 1。

⚠️ workName↔封面强依赖: 封面标题即 --title "${workName}"。一旦之后因 409 改名,必须用新 workName 重新合成封面(见 Step 8 改名重推流程),禁止旧封面配新名发布。

排布规则、视觉基线见 work-preparation.md#screenshot-layout-rules。

Output: coverImagePath。

Step 5: Introduction

读写 README 生成一句话简介。总字符数 15~50,脚本计数通过才继续:

node <skill>/scripts/count-cjk.mjs --file "$env:TEMP\intro.txt"   # Win 必须 --file(GBK 转码问题)

规则见 work-preparation.md#introduction-generation。

⏩ 并行:api.mjs GET "/v1/gallery/camps" --query "pageNo=1&pageSize=100&periodYear=${currentYear}" --creds-file "${credsFile}" --fields "id,name,school,status,startsAt,endsAt" 预取供 Step 7。

Output: introduction。

Step 6: Work Details

生成详解文章(500–1500 字)配图并打包 zip。

  1. 图表:必选系统架构图;可选 0–2 张(路由/依赖/统计图)。用 DevLens/GitNexus 理解项目后出图。禁用 emoji。
    python <skill>/scripts/generate_diagram.py --html diagram.html --out resources/<name>.png --width 1280
    python3 <skill>/scripts/verify-glyphs.py <img> --quiet   # 每张含中文图必跑
    
  2. 打包 zip + 校验一步到位(build-detail-zip.mjs 内置正确目录结构 README.md@根 + resources/,打包后自动跑服务端同源校验,跨平台无需 zip/ZipFile):
    node <skill>/scripts/build-detail-zip.mjs --readme <README.md> --resources <dir> --out <workDetail.zip>
    

Output: detailsZipPath。

Step 7: Select Training Camp

  1. 获取训练营列表(Step 5 预取则直接用)。
  2. 依据 startsAt/endsAt/status 判定投稿状态(api-spec.md#submission-status-determination)。
  3. 分「可投稿」/「不可投稿」两表展示,每行必须包含 school(学校)列;school 为空时显示 —。选不可投稿项提示「未开放投稿」。

Output: trainingCampId。

Step 8: Publish

  1. 宣示 开始发布作品 ${workName}。
  2. 门禁复核:node <skill>/scripts/check-gates.mjs --cover <png> --detail <zip> --strict --max-age 3600 --quiet(exit 0 才继续;publish-work.mjs 内置 verifyGates() 也会拦截)。
  3. 参数写入 UTF-8 JSON,Idempotency-Key=gallery-publish-${domainID}-${timestamp}:
    node <skill>/scripts/publish-work.mjs <utf8-params.json> --max-age 3600
    # 成功仅输出 workId/workName/workUrl/reward;失败原样输出完整响应
    
  4. 201 → 成功,取 workId/workUrl/reward,清理临时文件。积分提示(无论是否成功都必须提示「每日仅限一次」):
    • is_success===true:✅ 积分领取请求已提交。⚠️ 每日仅限一次。前往查看余额:https://developer.huaweicloud.com/grow
    • is_success===false:积分领取未成功:<error_msg> + 每日限一次提示 + 成长中心地址 + 反馈入口 https://gallery.developer.huaweicloud.com/gallery/profile?tab=feedback。
  5. 409 DUPLICATE → 停止当前发布。给选项:① 放弃 ② 改名重发。若改名重发,必须联动:
    1. 新名 workName'(<30 字符):用户自定,或在不带版本的常规名基础上加序号(如 扫雷→扫雷-2)。禁止随意拼接无关字符。
    2. 封面重生成(封面标题须与新名一致):用原截图 + 原 tagline/description,仅换 --title "<workName'>" 重新合成:
      python <skill>/scripts/generate_cover.py --screenshot <原截图png> --title "<workName'>" --tagline "<原tagline>" --description "<原description>" --out <coverImagePath-新> --scheme auto
      python3 <skill>/scripts/verify-glyphs.py <coverImagePath-新> --quiet   # exit 0 才可继续
      
    3. 门禁复核(封面已更新,须重跑):node <skill>/scripts/check-gates.mjs --cover <封面-新> --detail <zip> --strict --max-age 3600 --quiet。
    4. 用新 workName' + 新封面、新 Idempotency-Key 重新发布(回到第 3 步)。 注意:详情 zip 通常无需重做;仅当 zip 内 README 的标题或正文写了旧作品名(与新名不一致)时,才需要把旧名改为新名并重新打包详情 zip。
  6. 其他错误 → 告知 <msg>(<code>),保留临时文件,问是否修改重发。错误码见 error-codes.md。

References

Document用途何时读
troubleshooting.md网络/各步骤失败排查脚本报错→先查这里
error-codes.md平台 API 全错误码表API 返回非 2xx 时查表
api-spec.mdAPI 契约、投稿状态判定Step 7/8 解析响应
work-preparation.md命名/封面/简介/详情/图表统一规则Step 3–6 需细节时按目录跳转
work-preparation-windows.mdWindows 专属:PowerShell 预检/字体/zip仅 Windows
work-preparation-linux.mdLinux 专属:bash 预检/yum/fontconfig仅 Linux
windows-setup.mdWindows 首次准备:编码/Playwright/zipWindows 环境首次
self-verify-publish.md自委托 SELF_VERIFY 与 STS 原理Step 1 出问题时
devbridge-tunnel.mdDevBridge 隧道登录/故障Step 2 隧道异常
codearts-sandbox.mdCodeArts 沙箱目录Step 1 命中沙箱
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/devtools/common/huawei-cloud-publish-work-to-gallery

Default branch

master

Latest commit

f690d6e

Tree SHA

a8c0aba