huawei-cloud-publish-work-to-gallery について
プロジェクトをHuawei Cloudの大学向けギャラリープラットフォームに公開するためのスキルです。スクリプトによるプロジェクト選定、メタデータや画像の準備、公開を、各段階のチェックを通じて進めます。
主な機能
- 01候補プロジェクトのスキャン
- 02アカウントドメインの解決と STS 認証情報の取得
- 03Git リポジトリ情報と作品名の取得
- 04カバー画像と詳細アーカイブの準備
- 05公開前の前提条件チェック
活用シーン
- 01大学向けギャラリーへの作品公開
- 02作品のカバー画像と詳細パッケージの準備
- 03投稿先トレーニングキャンプの選択
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ huaweicloud/ huaweicloud-skills --skill huawei-cloud-publish-work-to-galleryインストール後、Claude Code で/huawei-cloud-publish-work-to-galleryを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api-spec.mdcodearts-sandbox.mddevbridge-tunnel.mderror-codes.mdiam-policies.mdmock-server-template.mdself-verify-publish.mdtroubleshooting.mdwindows-setup.mdwork-preparation-linux.mdwork-preparation-windows.mdwork-preparation.mdscripts/api.mjsbrowser_launch.pybuild-cover.mjsbuild-detail-zip.mjscheck-gates.mjscheck-version.mjscount-cjk.mjsdetect-env.mjsdownload-noto-color-emoji.shensure-git-root.mjsensure-gitcode-credential.mjsensure-user-bindir.mjsensure-user-tool.mjsensure-utf8.mjsextract-fonts.mjsextract-workname.mjsgen_sts.pygenerate_cover.py詳細
ギャラリーに作品を公開する
作品を華為クラウドの大学向け運営プラットフォームに公開します。組み込みスクリプトを優先して呼び出してください(単一のエントリーポイント、fail-fast、--help を内蔵)。エラーが発生した場合にのみ、references/troubleshooting.md を確認してください。
パイプライン
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 は相互に依存せず、4つすべてを並列実行します(最長経路の Step 4 が約90秒で、直列実行の約160秒ではありません)。Step 4 内の preflight と ensure-utf8 も並列実行します。Step 6 の隠れた依存関係に注意:generate_diagram.py は Playwright を使用し、Step 4 の preflight でインストールされます(初回は CJK フォントと Chromium を含み、5~10分)。スクリプトにはゲートが組み込まれており、font-gate-ok マーカーがない場合は exit 1 で待機を促すメッセージを表示し、ModuleNotFoundError は発生しません。Step 6 の並列実行時にこのメッセージが表示された場合は、preflight の完了後(ログ/マーカーをポーリングして確認)にこの手順を再実行してください。実際の失敗ではありません。
変数の引き継ぎ:port/workName/envUrl は最初の該当ステップで決定し、その後は全工程で変数として渡してください。ハードコードは禁止です(トンネル URL には port が含まれるため、ポートを変更すると envUrl も変わります)。
実行モデル:① スクリプトの契約を優先——stdout の成功シグナルに基づいて判定し、成功時はソースコードを一切読みません。失敗した場合にのみ、スクリプトのメッセージ → troubleshooting の該当セクション → スクリプトのソースコードを grep の順に確認します。② ゲートを手動で回避することは禁止です。③ ネットワークタイムアウトは一律 3s です。④ detect-env.mjs でプラットフォームを特定した後は、該当プラットフォームの reference のみを参照してください(ディレクトリをたどって確認し、すべてを読み込まないでください)。⑤ 依存関係のない bash 呼び出しはまとめる:; で連結して1つのコマンドにし、ツールの往復を減らしてください(1回につき約1~2秒)。⑥ ユーザーとの対話が必要なコマンドでは、リンク/QRコードをそのままユーザーに表示してください。エージェント内蔵のブラウザー/ツール(browser_use_open など)で代わりに開くことは禁止です——スクリプトはローカルでコールバックサーバーをすでに起動しており、ユーザーが任意のブラウザーで認証すると、スクリプトが自動的にトークンを取得します。エージェントは全工程を通じてブラウザーを必要としません。
コアコマンド(スクリプトの契約クイックリファレンス)
$SKILL_DIRの定義:この skill のインストールディレクトリの絶対パス(SKILL.md を含むディレクトリ)です。実行前にexport SKILL_DIR=/path/to/huawei-cloud-publish-work-to-galleryを設定してください(例:$HOME/.local/share/huawei-cloud-publish-work-to-gallery)。すべてのスクリプトは実行可能ファイル(shebang 付き)なので、$SKILL_DIR/scripts/…を先頭に付けて直接呼び出してください。node/python/bashのインタープリター接頭辞は不要です(この説明が当てはまるのは Linux のみです。Windows では .mjs/.py にnode/pythonの接頭辞が必要で、preflight.ps1にはpowershellの接頭辞が必要です)。インストーラーによって実行権限が復元されていない場合(Linux で直接呼び出すとPermission deniedが発生)、スクリプトを変更せずにchmod +x "$SKILL_DIR/scripts/"*を一度実行して修復してください。引数には必ず解析可能なサンプル値を使用してください(<…>のプレースホルダーは、コマンド抽出器によって削除されると引数不足/空値になるため使用しないでください)。W/R の表記:W= プラットフォームへの書き込み操作(作品の公開。必ずユーザーの確認後にのみ実行)。R= 読み取り専用の照会/ローカル補助コマンド。 | 手順 | スクリプト/コマンド | W/R | 成功のシグナル(exit 0 かつ) | 失敗(exit 1;2=引数エラー) | |------|-----------|-----|----------------------|-----------------------------------| | 前提 |$SKILL_DIR/scripts/api.mjs GET /v1/gallery/announcements/current --prefix open-api-guest| R | stdout の先頭行が#status=200| タイムアウト/接続拒否 → ネットワークの確認を案内 | | 前提 |$SKILL_DIR/scripts/check-version.mjs(自身の name/version を読み取り、/v1/gallery/skills/statusを呼び出して判定) | R | exit 0 かつ先頭行がstatus=ok/status=skip| exit 1(status=outdated+ プラットフォームのアップグレード文言)→ そのままアップグレードを案内して停止;判定ルールは api-spec を参照 | | 5/7 |$SKILL_DIR/scripts/api.mjs GET "/v1/gallery/camps" --creds-file ./sts-creds.json --fields "id,name,school,status,startsAt,endsAt"| R |#status=200| 401 → STS を更新 | | 1 |$SKILL_DIR/scripts/scan-projects.mjs| R | stdout が#project <n> <path> <type>| exit 1=候補なし | | 1 |$SKILL_DIR/scripts/resolve-domain.mjs --hcloud /usr/local/bin/hcloud| R | stdout が#domain=<id> name=<name>| exit 1=hcloud の失敗(stderr に確認手順を含む) | | 1 |$SKILL_DIR/scripts/gen_sts.py --account 100000000000 --hcloud /usr/local/bin/hcloud --creds-out ./sts-creds.json --sh-out ./sts-creds.sh| R |./sts-creds.json(_refreshを含む)と./sts-creds.sh(相対パスで、後続の--creds-file ./sts-creds.jsonからそのまま使用可能)を書き込む | [troubleshooting#domain-id-resolution-issues] を参照 | | 3 |$SKILL_DIR/scripts/ensure-git-root.mjs /path/to/project| R | exit 0(git -C /path/to/project rev-parse --git-dir=.git) | exit 1=workDir がリポジトリのルートではない → remote の読み取りを禁止し、Step 3 に従って対応 | | 3 |$SKILL_DIR/scripts/read-git-info.mjs /path/to/project| R |#gitUrl=<https://… .git>#gitBranch=<ブランチ>(リモートにそのブランチが実在することを確認済み) | exit 1=Git リポジトリではない/URL 検証失敗/#branchAbsent=1(リモートにブランチが存在しない——SHA に応じた対処は checkout または push のみ。stderr の内容をそのまま伝えればよい);ネットワーク/認証情報の問題で確認できない場合は stderr に警告を出すが、処理は妨げない(公開時にサーバー側でブランチの存在を検証) | | 3 |$SKILL_DIR/scripts/ensure-gitcode-credential.mjs| R |#credential=found(認証情報あり)または#credential=missing(認証情報なし、OAuth を使用) | exit 0;手動での代替手段なし | | 3 |$SKILL_DIR/scripts/gitcode-oauth.ensure.mjs --start| R |#oauth=ready(トークンあり)/#oauth=started session_id=123456 login_url=https://example.com(stdout は即時に返り、QR コードは stderr に出力) |#oauth=absentがない場合は exit 1;失敗時は#oauth=failed reason=timeoutで exit 1 | | 3 |$SKILL_DIR/scripts/gitcode-oauth.ensure.mjs --wait 123456 --timeout 300| R |#oauth=done(トークンが~/.gitcode/auth.tomlに書き込まれている) |#oauth=failed reason=timeout\|finish\|…で exit 1 | | 3 |$SKILL_DIR/scripts/extract-workname.mjs /path/to/project| R | stdout が#name=MyWork source=frontmatter| exit 1=workDir が存在しない | | 2 |$SKILL_DIR/scripts/spawn-detached.mjs --out /tmp/spawn.out --pidfile /tmp/app.pid --cwd /path/to/project -- npm run dev| R |#spawn=ok pid=12345 out=/tmp/spawn.out| exit 1=起動失敗 | | 2 | トンネル:まず$SKILL_DIR/scripts/detect-env.mjsを実行してtunnelフィールドを確認します。true(Linux)→ 組み込み skillhuawei-cloud-devbridge-tunnelを読み込んでトンネルを開きます。false(Windows/macOS)→ 読み込み禁止、envUrl=""| R |envUrlを取得;skill が利用できない/失敗した場合はenvUrl=""のまま通常どおり公開 | tunnel=false の場合にトンネルを開こうとする = 契約違反 | | 4 |$SKILL_DIR/scripts/preflight.sh(Win:powershell $SKILL_DIR/scripts/preflight.ps1) | R |font-gate-okを書き込む(ok=true gate=preflight) | スクリーンショット/カバー/図表の生成禁止 | | 4 |$SKILL_DIR/scripts/ensure-utf8.mjs /path/to/project| R |utf8-gate-okを書き込む | UTF-8 以外のエンコーディング → スクリーンショット禁止 | | 4 |$SKILL_DIR/scripts/build-cover.mjs --url http://127.0.0.1:8080 --project-dir /path/to/project --title "MyWork" --out /tmp/cover.png| R | stdout が 1 行#cover=/tmp/cover.png layout=… multi=yes tmp=/tmp/shots(内部でscreenshot_guard.pyとgenerate_cover.pyを呼び出す) | exit 1 → スクリーンショット/検証/合成のいずれかに失敗。詳細は stderr を参照 | | 4 |$SKILL_DIR/scripts/generate_cover.py --screenshot /tmp/shots/shot-index.png --title "MyWork" --out /tmp/cover.png| R | カバー PNG を生成し、その後verify-glyphs.pyで検証 | exit 1 → 合成の続行禁止 | | 4/6 |$SKILL_DIR/scripts/verify-glyphs.py /tmp/cover.png --quiet| R | exit 0(stdout はトークン節約のため 1 行のみ) | exit 1 → 豆腐文字の疑い → フォントを修正 | | 5 |$SKILL_DIR/scripts/count-cjk.mjs --file /tmp/intro.txt| R | 総文字数が 15~50 | exit 1 → 紹介文を書き直して再カウント | | 6 |$SKILL_DIR/scripts/generate_diagram.py --html /tmp/diagram.html --out /tmp/diagram.png --width 1280| R | 図表 PNG を生成し、その後verify-glyphs.py --quietで検証 | カバーと同様;font-gate-okがない場合は exit 1 で preflight の完了を待つよう案内(暗黙の依存関係。並列実行に関する説明を参照) | | 6 |$SKILL_DIR/scripts/build-detail-zip.mjs --readme README.md --resources /path/to/project/resources --out /tmp/detail.zip| R | パッケージ化と検証を一度に完了 | exit 1 → 出力に従って修正し、再パッケージ化 | | 8 |$SKILL_DIR/scripts/check-gates.mjs --cover /tmp/cover.png --detail /tmp/detail.zip --strict --max-age 3600 --quiet| R | exit 0(stdout はトークン節約のため 1 行のみ) | exit 1 → 戻ってゲートを再実行 | | 8 |$SKILL_DIR/scripts/publish-work.mjs /tmp/params.json --max-age 3600| W |#status=201(workId/workUrl/reward のみを出力) | envUrl に到達できない → exit 1(ローカルサービスの確認を案内);409/その他 → 完全なレスポンスをそのまま出力 | ファイル位置の目印:Linux/tmp/;Windowsos.tmpdir()(%TEMP%)。
パラメーターの確認
| パラメーター | 必須 | 説明 | 取得元 |
|---|---|---|---|
workDir | はい | 作品プロジェクトのルートディレクトリ(git リポジトリのルートである必要があります) | Step 1(ユーザーが選択) |
domainID | はい | Huawei Cloud アカウントの Domain ID | Step 1(resolve-domain.mjs) |
credsFile | はい | STS 一時認証情報 JSON(sts-creds.json) | Step 1(gen_sts.py) |
port | 条件付き | ローカルサービスのポート(ユーザーがプロジェクトの実行を拒否した場合は不要) | Step 2 |
envUrl | 条件付き | DevBridge トンネルのパブリック URL(失敗した場合は空文字列) | Step 2 |
gitUrl / gitBranch | はい | 作品リポジトリの URL/ブランチ | Step 3 |
workName | はい | 作品名(30 文字未満) | Step 3(extract-workname.mjs) |
coverImagePath | はい | カバー PNG(verify-glyphs の検証に合格する必要があります) | Step 4 |
introduction | はい | 1 文の紹介文(合計文字数 15~50) | Step 5(count-cjk.mjs) |
detailsZipPath | はい | 作品詳細 zip(ルートに README.md + resources/) | Step 6 |
trainingCampId | はい | トレーニングキャンプ/イベント ID | Step 7(ユーザーが番号で選択) |
前提条件と依存関係の固定
- hcloud + AK/SK:Step 1 で必要です。未インストール/未設定の場合 → troubleshooting#domain-id-resolution-issues。
- git:Step 3 で必要です。zip は
build-detail-zip.mjsが使用できない場合の代替手段です(Linuxyum install zip;Windows .NETZipFile。 windows-setup.md を参照)。 - Git Bash の前提条件:
source $SKILL_DIR/scripts/setup-env.sh(MSYS のパス変換を防止)。PowerShell/CMD では不要です。 - OAuth とローカル環境の依存関係(自動化/サンドボックスの制限):公開フローでは、ユーザーによる GitCode OAuth 認可(Step 3)とローカルプロジェクトの実行(Step 2 のトンネル/Step 8 の公開)が必要です。無人運用またはサンドボックス環境(ユーザーのブラウザーで認可できない環境)では、実際のプラットフォーム API にアクセスできません。このようなユースケースには
requires manual verificationと明記し、実際のユーザー環境で再検証してください。
コアワークフロー
Step 1: 作品ディレクトリの選択と IAM Domain 情報の解決
- ユーザーに通知します(ディレクトリの選択をもって同意とします):IAM の自己委任
SELF_VERIFYを作成し、STS 一時認証情報(900s)を生成します。永続的な AK/SK はローカルに保持し、アップロードしません。 - プロジェクトのルートをスキャンします:
$SKILL_DIR/scripts/scan-projects.mjs——**/README.mdを自動的に再帰検索し、指示ファイルを確認して、skills//node_modules//dist/などを除外し、CodeArts のサンドボックスディレクトリをスキャンします。stdout の各行は#project <n> <path> <type>です。 - 候補を列挙してユーザーの選択を待ち、
workDirに設定します。 - Domain ID を解決します:
$SKILL_DIR/scripts/resolve-domain.mjs --hcloud /usr/local/bin/hcloud——hcloud configure set --region+IAM KeystoneListAuthDomainsを自動実行し、domain_idを抽出します。stdout は#domain=<id> name=<name>です。認証情報の優先順位:env → 設定済みの hcloud → ユーザーに設定を案内(troubleshooting#2)。Windows ではinstall-hcloud.ps1によるインストールとユーザー PATH への追加が完了しているため、通常--hcloudは不要です。 - STS を生成します:
$SKILL_DIR/scripts/gen_sts.py --account 100000000000 --hcloud /usr/local/bin/hcloud --creds-out ./sts-creds.json --sh-out ./sts-creds.sh→./sts-creds.json(_refreshを含み、401 が発生すると自動更新します)。認証情報ファイルは相対パスで読み書きします(同じ CWD のセッション内では一貫しており、プラットフォームごとに/tmp/%TEMP%を使い分ける必要はありません);⚠️ この認証情報ファイルをgit addしたり、コミットしたりしないでください。Step 8 の終了後にまとめて削除します。hcloud の検出順序は resolve-domain と同じです。 - 出力:
IAM Domain ID: <id> を取得しました。作品をお客様の Huawei Cloud アカウントに関連付けるために使用します。
出力: workDir、domainID、credsFile。
Step 2: プロジェクトの実行とトンネルの開設
まず $SKILL_DIR/scripts/detect-env.mjs を実行して tunnel フィールドを取得します。true(Linux)の場合はトンネルを開くかどうかを尋ねます。false(Windows/macOS)の場合はトンネルを完全にスキップし、envUrl="" に設定して、DevBridge skill の読み込みを試みないでください。プロジェクトを実行するかユーザーに尋ねます。拒否された場合は envUrl="" として Step 3 に進みます。
- ポートの解放:
netstat -ano | findstr :<port>(Win)を実行し、残っているプロセスを kill します。 - プロジェクトを起動します:
$SKILL_DIR/scripts/spawn-detached.mjs --out /tmp/spawn.out --pidfile /tmp/app.pid --cwd /path/to/project -- npm run dev→#spawn=ok pid=12345。必ず--cwd <workDir>を指定してください(スクリプトのデフォルトはprocess.cwd()です。実行ディレクトリが workDir でない場合、http-server .が誤ったディレクトリを配信し、スクリーンショットが空白になります——2026-09-20 の教訓)。エントリースクリプトを優先します(npm run dev/python main.py)。フロントエンドのみの場合はhttp-server . -p <port>を使用します。30 秒以内にヘルスチェックを行います:curl -sf --max-time 3 http://localhost:<port>。 - トンネル(DevBridge):Linux では、対象環境に組み込まれている skill
huawei-cloud-devbridge-tunnelを読み込み、その手順に従ってトンネルを開設し、envUrlを取得してください——DevBridge コマンドを推測したり、独自に組み立てたりしないでください。この skill が使用できない場合、またはトンネルの開設に失敗した場合は、envUrl=""として通常どおり公開します。Windows では DevBridge を使用しません(トンネル機能が組み込まれていません)→envUrl=""。公開終了後にトンネルを自動でクリーンアップしないでください——公開の終了はトンネルのライフサイクルの終了を意味しません(後続の公開や 409 による名前変更の再試行でトンネルが再利用されることがあります)。ユーザーが明示的にクリーンアップを求めた場合に限り、組み込み skill の手順に従ってストリームを停止/トンネルを削除してください。詳しくは devbridge-tunnel.md を参照してください。
出力: port、envUrl(または "")。
Step 3: Git Repository Info & Work Name
gitUrl 必填,gitBranch 必须显式读取。workName 从 README 解析/合成(<30 字符)。
- 仓库根检测(fail-stop):
$SKILL_DIR/scripts/ensure-git-root.mjs /path/to/project——硬检测 workDir 自身是否为 git 仓库根(git -C /path/to/project rev-parse --git-dir必须返回.git)。若不是(如 workDir 无 .git 但父目录有,git 会向上递归返回父仓库 remote),脚本 exit 1 并提示。此时 禁止 直接git -C /path/to/project remote get-url origin(会拿到父仓库 URL)。处理方式:① 问用户手动提供gitUrl+gitBranch;② 或在 workDirgit init+ 推到远端后再读。检测通过才继续。 $SKILL_DIR/scripts/read-git-info.mjs /path/to/project一步取 gitUrl/gitBranch(含仓库自检 + 凭证剥离 + 远端分支核对,契约见上表)。#branchAbsent=1→ 转述 stderr 的唯一处置(脚本已按 SHA 判定:远端某分支与本地当前提交一致 →git checkout <该分支>后重跑,无损且优于 push;否则 →git push -u origin <branch>后重跑,切到远端旧分支会提交旧代码)。- 凭证排查:
$SKILL_DIR/scripts/ensure-gitcode-credential.mjs——有凭证即#credential=found。无凭证时走 gitcode-oauth 两阶段授权(契约见上方gitcode-oauth.ensure.mjs --start/--wait):①--start拿登录链接/二维码原样展示给用户,请用户在任意浏览器打开授权(禁止用 agent 内置浏览器代开),脚本本地已起回调服务器;②--wait <session_id>阻塞轮询到 token 落盘。 - 命名:
$SKILL_DIR/scripts/extract-workname.mjs /path/to/project——按优先级 frontmatter → H1 → manifest →index.html <title>→ 目录名提取。stdout#name=<name> source=<来源>。source=dirname时 agent 可合成/修改(<30 字符)。
Output: gitUrl、gitBranch、workName。
Step 4: Cover Image
门禁(并行):
| 门禁 | 命令 | 标记 |
|---|---|---|
| 渲染 | $SKILL_DIR/scripts/preflight.sh(Win: $SKILL_DIR/scripts/preflight.ps1) | font-gate-ok |
| 编码 | $SKILL_DIR/scripts/ensure-utf8.mjs /path/to/project | utf8-gate-ok |
门禁失败禁止截图/合成。preflight 以标记文件 ok=true 为准,Linux 一律后台化启动(首次下载 Chromium 慢网 5~10 分钟)。轮询上限与心跳/卡死换源判定见 work-preparation-linux.md#preflight-后台化与轮询linux。
封面一键生成(内置:页数判定 + 单/多图概率抽样 + 截图 + 合成 + 校验):
$SKILL_DIR/scripts/build-cover.mjs \
--url "http://127.0.0.1:8080" --project-dir /path/to/project \
--title "MyWork" --tagline "一句话简介" --description "主体介绍,1~3 句" \
--out /tmp/cover.png
- 布局决策在脚本内部闭环(单/多页自动判定 + 布局概率抽样 + 失败页自动跳过,agent 无感知),规则详见 work-preparation.md。
- stdout 仅输出一行结果:
#cover=… layout=… multi=yes|no pages=<n> scheme=… tmp=<截图临时目录>;日志走 stderr。失败 exit 1。 - 截图临时目录
tmp=<abs>保留到整体流程结束(供 Step 8 409 改名复用原截图,见下),由 Step 8 发布成功/放弃后统一清理(Remove-Item -Recurse -Force <abs>或rm -rf <abs>),build-cover 不删。
⚠️ workName↔封面强依赖: 封面标题即
--title "${workName}"。一旦之后因 409 改名,必须用新 workName 重新合成封面(见 Step 8 改名重推流程),禁止旧封面配新名发布。
输出
coverTmp:从 build-cover stdout 的tmp=提取并作为变量贯穿到 Step 8(409 改名时--screenshot ${coverTmp}/shot-index.png)。
排布规则、视觉基线见 work-preparation.md#screenshot-layout-rules。
Output: coverImage(封面 PNG 绝对路径)。
Step 5: Introduction
读写 README 生成一句话简介。总字符数 15~50,脚本计数通过才继续:
$SKILL_DIR/scripts/count-cjk.mjs --file "$env:TEMP\intro.txt" # Win 必须 --file(GBK 转码问题)
规则见 work-preparation.md#introduction-generation。
⏩ 并行:预取活动列表供 Step 7——表行 5/7 命令 +
--query "pageNo=1&pageSize=100&periodYear=${currentYear}"。
Output: introduction。
Step 6: Work Details
生成详解文章(500–1500 字)配图并打包 zip。
- 图表:必选系统架构图;可选 0–2 张(路由/依赖/统计图)。用 DevLens/GitNexus 理解项目后出图。禁用 emoji。
$SKILL_DIR/scripts/generate_diagram.py --html /path/to/project/diagram.html --out /path/to/project/resources/architecture.png --width 1280 $SKILL_DIR/scripts/verify-glyphs.py /path/to/project/resources/architecture.png --quiet # 每张含中文图必跑 - 打包 zip + 校验一步到位(
build-detail-zip.mjs内置正确目录结构 README.md@根 + resources/,打包后自动跑服务端同源校验,跨平台无需 zip/ZipFile):$SKILL_DIR/scripts/build-detail-zip.mjs --readme /path/to/project/README.md --resources /path/to/project/resources --out /tmp/detail.zip
Output: detailZip(详情 zip 绝对路径)。
Step 7: Select Activity
- 获取活动列表(Step 5 预取则直接用,
$SKILL_DIR/scripts/api.mjs GET /v1/gallery/camps输出items数组)。 - 依据
startsAt/endsAt/status判定投稿状态(api-spec.md#submission-status-determination)。 - 分「可投稿」/「不可投稿」两表展示,每行按当前列表顺序编号(
<n>. <activity name> — <school>(状态)),必须包含school(学校)列;school为空时显示—。用户回序号选择活动(编号对应items数组下标序),选不可投稿项提示「未开放投稿」。
Output: trainingCampId。
Step 8: 公開
作品 ${workName} の公開を開始しますと宣言します。- ゲートを再確認:
$SKILL_DIR/scripts/check-gates.mjs --cover /tmp/cover.png --detail /tmp/detail.zip --strict --max-age 3600 --quiet(exit 0 の場合のみ続行します。publish-work.mjsに組み込まれたverifyGates()でもブロックされます)。publish-work.mjsはリクエスト送信前にenvUrlに到達できるかも検証します(curl -sf --max-time 10)。トンネルに接続できない場合は exit 1 で終了し、ローカルサービスを確認するよう通知します。 - パラメーターを UTF-8 JSON に書き込みます。Idempotency-Key=
gallery-publish-${domainID}-${timestamp}。パラメーターの key はpublish-work.mjs --helpを参照してください(値は出力変数に対応します:coverImage←Step 4、detailZip←Step 6、trainingCampId←Step 7、gitUrl/gitBranch←Step 3、envUrl←Step 2)。domainIdはパラメーターに含めません(Idempotency-Key の組み立てにのみ使用)。credsFileは JSON に含めません(STS の 3 フィールドaccessKeyId/secretAccessKey/securityTokenをインラインで指定します):$SKILL_DIR/scripts/publish-work.mjs /tmp/params.json --max-age 3600 # 成功仅输出 workId/workName/workUrl/reward;失败原样输出完整响应 - 201 → 成功です。
workId/workUrl/rewardを取得し、一時ファイル(Step 4 のcoverTmpスクリーンショットディレクトリを含む)を削除します。ポイントに関する案内(成功・失敗にかかわらず、「1 日 1 回のみ」と必ず案内します):is_success===true:✅ ポイント獲得リクエストを送信しました。⚠️ 1 日 1 回のみです。残高を確認:https://developer.huaweicloud.com/growis_success===false:ポイントを獲得できませんでした:<error_msg>+ 1 日 1 回のみの案内 + 成長センターの URL + フィードバック窓口https://gallery.developer.huaweicloud.com/gallery/profile?tab=feedback。
- 409 DUPLICATE → 現在の公開を停止します。次の選択肢を提示します:① 中止する ② 名前を変更して再送する。名前を変更して再送する場合、以下を必ず連動させます:
- 新しい名前
workName'(30 文字未満):ユーザーが指定するか、バージョン表記のない通常の名前に連番を追加します(例:掃雷→掃雷-2)。無関係な文字を任意に付け加えることは禁止です。 - カバーを再生成(カバーのタイトルは新しい名前と一致させます):**Step 4 で保持した元のスクリーンショット(
${coverTmp}/shot-index.png)**と元の tagline/description を再利用し、--title "<workName'>"のみ変更してbuild-cover.mjsを再実行します(スクリーンショットの上書き・合成・検証を一括で実行し、終了後に tmp を再処理しません):$SKILL_DIR/scripts/build-cover.mjs --url http://127.0.0.1:8080 --project-dir /path/to/project \ --screenshot ${coverTmp}/shot-index.png --title "NewName" \ --tagline "原tagline" --description "原description" --out /tmp/cover-new.png $SKILL_DIR/scripts/verify-glyphs.py /tmp/cover-new.png --quiet # exit 0 の場合のみ続行できますcoverTmpがすでに削除されている、または存在しない場合は、--screenshotを付けずにbuild-cover.mjsを再実行します(スクリーンショットを撮り直します。ローカルサービスが引き続き稼働している必要があります)。 - ゲートを再確認(カバーを更新したため、再実行が必要です):
$SKILL_DIR/scripts/check-gates.mjs --cover /tmp/cover-new.png --detail /tmp/detail.zip --strict --max-age 3600 --quiet。 - 新しい
workName'と新しいカバー、新しい Idempotency-Key を使って再公開します(手順 3 に戻ります)。最終的に成功または中止した後、いずれの場合も各coverTmpを削除します。 注意:詳細 zip は通常、作り直す必要はありません。zip 内の README のタイトルまたは本文に古い作品名(新しい名前と一致しないもの)が記載されている場合に限り、古い名前を新しい名前に変更して、詳細 zip を再パッケージ化する必要があります。
- 新しい名前
- その他のエラー →
<msg>(<code>)を通知し、一時ファイルを保持して、修正して再送するかを確認します。エラーコードについては error-codes.md を参照してください。
参考資料
| ドキュメント | 用途 | 読むタイミング |
|---|---|---|
| troubleshooting.md | ネットワーク/各手順の失敗時のトラブルシューティング | スクリプトでエラーが発生した場合→まずここを確認 |
| error-codes.md | プラットフォーム API の全エラーコード一覧 | API が 2xx 以外を返した場合に確認 |
| api-spec.md | API 契約、投稿ステータスの判定 | Step 7/8 でレスポンスを解析 |
| work-preparation.md | 名前/カバー/紹介文/詳細/図表の共通ルール | Step 3–6 で詳細が必要な場合は目次から該当箇所へ |
| work-preparation-windows.md | Windows 専用:PowerShell の事前確認/フォント/zip | Windows のみ |
| work-preparation-linux.md | Linux 専用:bash の事前確認/yum/fontconfig | Linux のみ |
| windows-setup.md | Windows の初回準備:エンコーディング/Playwright/zip | Windows 環境での初回 |
| self-verify-publish.md | 自己委任 SELF_VERIFY と STS の仕組み | Step 1 で問題が発生した場合 |
| iam-policies.md | 最小権限 IAM ポリシー(Domain の照会 + SELF_VERIFY の自己委任) | Step 1 で AK/SK の権限を設定する場合 |
| devbridge-tunnel.md | DevBridge トンネル:Linux では組み込みの huawei-cloud-devbridge-tunnel skill を使用/Windows では非推奨 | Step 2 のトンネル(Linux/Windows) |
| codearts-sandbox.md | CodeArts サンドボックスディレクトリ | Step 1 でサンドボックスが検出された場合 |