create-babylon-app v1.0に向けたアプデ作業
去年の今頃に、create-babylon-appというCLIを作って公開してみた
forumに投稿したところ、たまーに誰かがリプをくれる、くらいになった
実はちょいちょい使われている?(検索でヒットする?)かもしれないので、
このさいちゃんとメンテしていきたいなぁという気持ちがあったのである
というのと、自分も使うんだけど正直まだ使い勝手は良いわけではないので
自分で使うようにちゃんとやっていきたい
Project Kanbanを整えるなどしていた
v1.0に向けてやりたいことをやっていくぞ!
やりたいこと
- テンプレートの拡充と将来的なテンプレ追加に対応できる選択アルゴリズム
- CLIの動作をモダン化
- cittyへの移行
- inquireのために対応してるcjsでの実行をvite-nodeにする
- CI/CD, Test
- 公式ドキュメントWebサイト
v1.0ではモダン化は対応したいけど
Babylon.js 7対応とか、便利なテンプレート追加とか、CICD対応とかは0.2で出しちゃってもいいかも
nuxiを見ていたら、どうやらunjs/gigetというものを使ってテンプレートをダウンロードしているらしい
ほぇ~~すげぇ使ってみたい
あと、ビルドはunjs/unbuild、tsの実行にはunjs/jitiが使えるらしい
なんかunjsが強すぎる
とりあえずnuxt/cliの中身を解析してみることにした
ファイル構成自体はすごいシンプルな感じなので読めそう
nuxi、というか割とそういう系のCLIは
コアな機能をimportして使うことができるようになっている
ん-、nuxiを使ったCLIを作ろうと思った時に便利なのかなぁ
なのでpackage.jsonではこんな感じの表記になっている
{
...
"type": "module",
"exports": {
".": "./dist/index.mjs",
"./cli": "./bin/nuxi.mjs"
},
"types": "./dist/index.d.ts",
"bin": {
"nuxi": "./bin/nuxi.mjs",
...
},
"files": [
"bin",
"dist"
],
...
}
まぁ今回は通常のスクリプトで使う用のimportは考えなくていいかなぁ、たぶん使わんだろうし
現状のcreate-babylon-appでは/index.cjs
で/dist/index.js
をrequireして使ってるけども
nuxiでは、/bin/nuxi.mjs
で/dist/index.mjs
のrunMainを呼び出しているようだな
build.config.ts
はunbuildのコンフィグなのかなぁ
packagejsonのbuildコマンドにはunbuildとしか書かれていないので、
おそらくデフォでunbuildは./dist/index.mjsを生成する感じかなぁと思った
それで、/bin/nuxi.mjsはもともと設置しているので、それをCLIでは呼び出すようにしていると
nuxiのコードリーディングを進めている
どうやら、cittyは普通にコマンドライン引数とかコマンドをいい感じにしてくれるやーつらしい
defineCommandというやつでコマンドを定義できるんだけど、そこにサブコマンドとかargsを定義できる
nuxiの場合は以下のような構造
└─ nuxi <-------------------- main command
├─ init <---------------- sub command
│ └─ args
│ ├─ --dir
│ ├─ --template
│ └─ ...
├─ dev <----------------- sub command
│ └─ args
│ └─ ...
├─ info <---------------- sub command
└─ ...
subであれmainであれ、これらはcommand
というオブジェクトで、
commnadはネスト出来る仕組みらしい
commandで実行する処理はrun
メソッドで定義でき、
多分だけど、ctx.data
で親コマンドのデータを受け取れそう
対話型インターフェースはconsola.promptがやってくれそう
実質inquireの代替かな?
何となくわかってきたので、テスト用のCLIを一回作ってみようと思う
testbedプロジェクトで作業中
unbuildを導入してtsをビルドし、それをCLIとして実行するまでのテスト環境を整備
const helloLog = () => {
console.log("Hello");
};
export const runMain = helloLog;
export * from "./main"
import { runMain } from "../dist/index.mjs";
runMain();
{
"name": "unjs-stack-cli-testbed",
"version": "1.0.0",
"description": "",
"main": "src/index.ts",
"files": [
"dist"
],
"scripts": {
"build": "unbuild",
"start": "node ./bin/cli.mjs"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"unbuild": "^2.0.0"
}
}
pnpm build && pnpm start
これでHelloが出力される
これから導入して試したいパッケージ達
- citty
- consola
- giget
- Biome
Biomeを導入してみたら、マジで手軽すぎてビビった
cittyもconsolaも試した
ついでにjitiによるtsの実行もできるようになった、最高だな
なんか、自分の環境ではconsolaはdevDependencyではなくdependencyにいれないと
mjs実行時にエラーになった
error ReferenceError: prompt is not defined
一旦こんな感じに
giget試すか
gigetのexample
githubの特定のディレクトリからもいけるんや!これはいいな
# Clone /test directory from main branch
npx giget@latest gh:unjs/template/test
ということでさっそく試してみよう
giget、めっちゃよいな・・・
const templateName = await consola.prompt("Which template do you use?", {
type: "select",
options: ["vite-ts", "vite-js"],
});
const doInstall = await consola.prompt("Install dependencies?", {
type: "confirm",
});
const { dir, source } = await downloadTemplate(
`gh:drumath2237/create-babylon-app/templates/${templateName}`,
{ install: doInstall, dir: `test-temp/${name}` }
);
console.log(dir, source);
gigetでテンプレートをGitHubから取得する部分の実装できた
今日は、create-babylon-appで
ESLint/Prettier --> Biomeへ移行した
リリース・ブランチ戦略を考えていた
さて、散々迷った結果やっぱり上がいいか~ってなったよ(おい
GitHub Actionsのジョブの分け方の作法があまり分かっていなくて、ちょっと手が止まってる感じがする
今やりたいことって、たぶん単一のyamlファイルで実現できると思うし
多分それがいいような気はしている
というのも、リリース時にはやっぱりPRのジョブでしているようなビルドステップが必要なので
DRY的に重複したジョブの記述したくないなぁという
構造としては
- PRコミットPush時
- 各種セットアップ
- 静的テスト
- ビルド
-
main
へrelease/*
ブランチマージ時- PRコミット時のジョブを待機
- npm publish
ジョブやステップの記述はできるけど
イベントが駆動する条件設定の方法がわからないな
pull_reqのマージ元ブランチ名はhead_ref
でとれるらしい
マージ時のワークフローはこれらしい
on:
pull_request:
branches:
- master
types: [closed]
jobs:
tag:
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true
いったん、こんな感じにyamlを書いてみた
name: Build and Publish
on:
pull_request:
jobs:
build_and_test:
runs-on: ubuntu-22.04
strategy:
matrix:
node-version: [20]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "pnpm"
registry-url: https://registry.npmjs.org
- name: Install dependencies
run: pnpm install
- name: Static test
run: pnpm run check:ci
- name: Build
run: pnpm run build
release:
runs-on: ubuntu-22.04
needs: build_and_test
# releaseブランチからmainにPRがマージされたら
if: |
github.event.pull_request.merged == true
&& github.base_ref == 'main'
&& startsWith(github.head_ref, 'release/')
steps:
- name: Publish
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
GitHub でBranch Protection Rulesを設定
今のリリース戦略であればmainに直Pushしなくてすむので、直Pushを抑制する
そしてlerna-liteのallowBranchを設定したところ
mainブランチでlerna versionコマンドが使えなくなってよかった
{
"$schema": "node_modules/@lerna-lite/cli/schemas/lerna-schema.json",
"version": "0.1.5",
"npmClient": "pnpm",
"packages": ["./"],
"command": {
"version": {
"allowBranch": ["release/*"]
}
}
}
あら、lerna versionは作動したけど
そのあとのnpm publishのジョブが起動しなかった
これはおそらく、releaseジョブがbuildジョブに依存しているけど
buildジョブはpull_reqしか指定していないから
マージ時に動作しなかったんだな
ピエ・・・releaseフローは起動したのに失敗してる・・・なんで・・・
Run npm publish
npm publish
shell: /usr/bin/bash -e {0}
env:
NODE_AUTH_TOKEN: ***
npm error code ENOENT
npm error syscall open
npm error path /home/runner/work/create-babylon-app/create-babylon-app/package.json
npm error errno -2
npm error enoent Could not read package.json: Error: ENOENT: no such file or directory, open '/home/runner/work/create-babylon-app/create-babylon-app/package.json'
npm error enoent This is related to npm not being able to find a file.
npm error enoent
npm error A complete log of this run can be found in: /home/runner/.npm/_logs/2024-07-04T15_42_02_824Z-debug-0.log
Error: Process completed with exit code 254.
何だこのパス /home/runner/work/create-babylon-app/create-babylon-app/package.json
上記はおそらく、checkoutするようにしたら大丈夫になった!
けど別のエラー。これが全くわからない
npm notice
npm notice 📦 create-babylon-app@0.2.0
npm notice Tarball Contents
npm notice 11.4kB LICENSE.md
npm notice 780B README.md
npm notice 48B index.cjs
npm notice 1.4kB package.json
npm notice 29B templates/test/index.js
npm notice 64B templates/test/package.json
npm notice 348B templates/vite-js/index.html
npm notice 1.5kB templates/vite-js/main.js
npm notice 264B templates/vite-js/package.json
npm notice 161B templates/vite-js/style.css
npm notice 371B templates/vite-ts/index.html
npm notice 299B templates/vite-ts/package.json
npm notice 1.4kB templates/vite-ts/src/createScene.ts
npm notice 517B templates/vite-ts/src/main.ts
npm notice 161B templates/vite-ts/src/style.css
npm notice 38B templates/vite-ts/src/vite-env.d.ts
npm notice 446B templates/vite-ts/tsconfig.json
npm notice Tarball Details
npm notice name: create-babylon-app
npm notice version: 0.2.0
npm notice filename: create-babylon-app-0.2.0.tgz
npm notice package size: 7.0 kB
npm notice unpacked size: 19.2 kB
npm notice shasum: 80b73168539a58e258d913b6c0326370f8046748
npm notice integrity: sha512-+h8ZyUGGBsDuj[...]jrFEif20nAXog==
npm notice total files: 17
npm notice
npm error code ENEEDAUTH
npm error need auth This command requires you to be logged in to https://registry.npmjs.org/
npm error need auth You need to authorize this machine using `npm adduser`
npm error A complete log of this run can be found in: /home/runner/.npm/_logs/2024-07-04T16_24_55_275Z-debug-0.log
GitHubの設定でRepository SecretsにNPM_TOKEN
を設定しているし、
それをymlでNODE_AUTH_TOKEN
に環境変数として設定しているのに、なぜだ?
一回GitHUb Actionsでnpm publishする方法を勉強しなおすか
しかし、ここはまえと変更していないはずなんだけどなぁ
TOKENも、classicだけどAutomationで作り直したんだが
これらを見ていたら、setup-nodeしていないから……?って思ってきたぞい
おっ、どうやらそうだったらしい
そして、余計なことした(興味本位でつけたProvenance)ことにより、エラーで失敗
これはどこかの記事で見たな、なんかpermissionを与えなくちゃいけないらしい
2024-07-04T16:51:31.4722126Z npm error code EUSAGE
2024-07-04T16:51:31.4733888Z npm error Provenance generation in GitHub Actions requires "write" access to the "id-token" permission
この記事がドンピシャだ
やった~~~リリースフロー動いた!!
いやはや、ここまでGitHub Actionsで苦戦することになるとは……
やっぱりちゃんと基礎を勉強しないとだめだな
割と雰囲気でいじっちゃってるから
まずい、リリースしたは良いものの、これ実行するとエラーになる
Error: Cannot find module './dist/index.js'
Require stack:
- C:\Users\2237k\AppData\Local\pnpm-cache\dlx\umiaujrtdk34onymzibtmx4bui\1907ed94d3c-36d8\node_modules\.pnpm\create-babylon-app@0.1.6\node_modules\create-babylon-app\index.cjs
at Module._resolveFilename (node:internal/modules/cjs/loader:1048:15)
at Module._load (node:internal/modules/cjs/loader:901:27)
at Module.require (node:internal/modules/cjs/loader:1115:19)
at require (node:internal/modules/helpers:130:18)
at Object.<anonymous> (C:\Users\2237k\AppData\Local\pnpm-cache\dlx\umiaujrtdk34onymzibtmx4bui\1907ed94d3c-36d8\node_modules\.pnpm\create-babylon-app@0.1.6\node_modules\create-babylon-app\index.cjs:2:1)
at Module._compile (node:internal/modules/cjs/loader:1241:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1295:10)
at Module.load (node:internal/modules/cjs/loader:1091:32)
at Module._load (node:internal/modules/cjs/loader:938:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'C:\\Users\\2237k\\AppData\\Local\\pnpm-cache\\dlx\\umiaujrtdk34onymzibtmx4bui\\1907ed94d3c-36d8\\node_modules\\.pnpm\\create-babylon-app@0.1.6\\node_modules\\create-babylon-app\\index.cjs'
]
}
結局のところ、いい感じにワークフロー自体を分離することで解決しました
やはりリリース時にdistが生成されていなかったのが問題だったようで、普通に解決した
という感じで、v0.1.7もそっこーリリース
0.1.7以降初の開発作業 ゆるほめLTでの発表があったので、それの資料準備などをやっていた
直近は、いったんビルド基盤をtsc->unbuildに移行して
.mjsを実行する形を目指すよ
unbuild、なぜか依存関係に廃止されたぱっけーじなのかな、があるらしく
ちょっと気になりますね
おもむろにpnpm exec unbuild
してみる
ん~普通にmjs出力されたね?
mjsは出力されたけど、実行はできなかったな
import { copy, readJSON, writeJson } from 'fs-extra';
^^^^^^^^
SyntaxError: Named export 'readJSON' not found. The requested module 'fs-extra' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'fs-extra';
const { copy, readJSON, writeJson } = pkg;
fs-extraがconnonjsなんだ
ん~そんなこと前に言われたっけな
お、fs-extraにESMを使う方法も書いてあった
試してみるか
esm版をインポートしてみたら、今度は別のエラーが出た
あ~たしかに、fs-extraでは./esm.mjsではなく./esmでexportしているので
其れで動かなかったらしいな
ん~~いろいろやっていたら、できた
特にこれはtsconfigとか、そこら辺の変更が大きかったかなぁ
一応unbuildでも動くようにしたけど、最終的にfs-extraとか排除したいので
大部分はあまり意味はなかったかもしれない
とはいえ、unbuildに移行してmjsで動くようになったのは何となく嬉しい
citty, jiti, consolaへの移行作業を進めていく
jitiへの移行はたぶん秒で終わるので対応しちゃいたいな
cittyとconsolaの順番は悩ましいな
しかしcittyのほうが変えるものが多いので、最初にconsolaのほうがいいかも
cittyに移行する際に、最初に簡単な対応をまずやってしまって
そのあとにちゃんと設計されたやり方をしたい
すなわち、最終的に得たい入力からコマンドライン引数を定義したり
テンプレート選択のロジックをスマートにしたい
どうやら、consolaのpromptのselectには型に関する不具合があり、まだ治っていないらしい
ここでlanguage
は{value, label}
が返ってきそうだけど、
実態はstringだった
基本的な置き換えはすぐできたな
あまり迷わずすぐ着手すべきだった
ということでcottyやconsolaなどが加わったバージョンがmainにマージされた
インターフェースが変わったのでv0.2.0だな次は
- pkgtype
- コマンドライン引数
- gigetによる読み込み
ここらへんやりたい
UnJS技術スタックへの移行はいい感じにできたので、v-tokyoで発表した
そして記事も書いた
次は便利テンプレートの追加をやっていきたい
考えていることは以下
- どんなテンプレを追加するのかを考えたい
- まぁでも、simple、playground、libraryかなぁ
- libraryはちょっと難易度高めというか、なにが妥当なテンプレとなるのかも含めて検討が必要そう
- どうやって進めようか
- gigetを使ってテンプレDLするようになったので、いったんGitHubに上げる必要がある
- テンプレ追加のPRをマージして、そのあとにテンプレ選択の実装PRを作る感じかなぁ
- ホントはもっとスマートな方法がいいな
- この後の話
- コマンドライン引数
- ドキュメント整備
テンプレートの構成
- ✨simple
- ts
- js
- ⛱playground
- ts
- js
- 🛠library
下記PRにより、必要なテンプレをリポジトリに追加までをした
ここから、ユーザ入力によってgithubからテンプレダウンロードを実装する
template選択のための再帰関数の実装ができた!
これであらゆる形式のテンプレート構造にも対応できそうだ
コマンドライン引数について考える
create-babylon-appでは最終的に、コマンドライン引数を使ってすべての設定項目を網羅できるようにしたい
なぜかというと、もしかしたら(CIとかで?)機械的にプロジェクトを生成したい人がいるかもしれなくて、そうなったときに対話式の入力は相性が悪いので
とはいえ、今収集している情報って
- プロジェクト名
- テンプレート名
- インストールするか?
なので、これらを設定できれば良い
project name | --name | -n | string |
template name | --template | -t | string |
do install | --install | -i | boolean |
さて、機能は十分実装ができたんで
あとはDEMO動画を撮るぞい
terminalizerを使うにせよ、普通に動画を撮るにせよ
pnpm create babylon-app を使うには現状をリリースしないといけない
あれ、そうなんだっけ
ついに!v1.0リリーーース!!
Forumへの投稿もDONE!
よし、目標を達成できたので、
いったんこのスクラップはクローズします