Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: plugin pack command for 2 #916

Open
wants to merge 58 commits into
base: main
Choose a base branch
from
Open

Conversation

tasshi-me
Copy link
Member

@tasshi-me tasshi-me commented Oct 24, 2024

Why

Support plugin manifest v2.

What

  • refactor plugin module
  • support manifest v2
  • add plugin info command

How to test

Manual test example:

## Prepare plugin project to /tmp/hello-kintone

## Build cli-kintone
pnpm install
pnpm build

## Show pack --help
node cli.js plugin pack --help

## Run pack command
node cli.js plugin pack --input /tmp/hello-kintone/src/ --output /tmp/dist/plugin.zip

ls /tmp/dist # => plugin.zip and .ppk exist

## Run pack command with ppk file
node cli.js plugin pack --input /tmp/hello-kintone/src/ --output /tmp/dist/plugin-2.zip --private-key /tmp/dist/*.ppk

ls /tmp/dist # => plugin.zip, plugin-2.zip, and .ppk exist

## Run info command
node cli.js plugin info --input /tmp/dist/plugin.zip # => printing plugin id, name, etc.

Checklist

  • Read CONTRIBUTING.md
  • Updated documentation if it is required.
  • Added/updated tests if it is required. (or tested manually)
  • Passed pnpm lint and pnpm test on the root directory.

@tasshi-me
Copy link
Member Author

tasshi-me commented Oct 25, 2024

Base automatically changed from feat/plugin-packer to main October 25, 2024 08:15
Copy link
Member Author

@tasshi-me tasshi-me left a comment

Choose a reason for hiding this comment

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

補足コメント書きました。
かなり大胆にリファクタしたので、↓の概念図も参考にしてください! 🙏

image

"node-rsa": "^1.1.1",
"stream-buffers": "^3.0.3",
Copy link
Member Author

Choose a reason for hiding this comment

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

stream-buffersは Node.js 標準の Utility Consumers に置き換えが案内されていたので置き換えた。
https://www.npmjs.com/package/stream-buffers

@@ -112,13 +110,9 @@
"chokidar": "^4.0.1",
"csv-parse": "^4.16.3",
"csv-stringify": "5.6.5",
"debug": "^4.3.7",
Copy link
Member Author

Choose a reason for hiding this comment

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

debug はcli-kintoneのlogger.debug|traceに置き換えた。

"https-proxy-agent": "^7.0.5",
"iconv-lite": "^0.6.3",
"mkdirp": "^3.0.1",
Copy link
Member Author

Choose a reason for hiding this comment

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

fs.promises.mkdir(data, {recursive: true}) に置き換え

@@ -112,13 +110,9 @@
"chokidar": "^4.0.1",
"csv-parse": "^4.16.3",
"csv-stringify": "5.6.5",
"debug": "^4.3.7",
"execa": "^9.4.1",
Copy link
Member Author

Choose a reason for hiding this comment

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

使用していたテストを消した。

Comment on lines +1 to +4
export { PublicKey } from "./public-key";
export type { PublicKeyInterface } from "./public-key";
export { PrivateKey } from "./private-key";
export type { PrivateKeyInterface } from "./private-key";
Copy link
Member Author

Choose a reason for hiding this comment

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

PublicKey と PrivateKey は変わることは当面なさそうだしInterfaceを切らなくても良さそう。
(アルゴリズムなどが変わるタイミングでIFを切れば良さそう)


const debug = _debug("packer");

const packer = (
Copy link
Member Author

Choose a reason for hiding this comment

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

packerの処理はPluginZip.build()に移動した。

import packer from "./index";
import { createContentsZip } from "./create-contents-zip";

export const packPluginFromManifest = (
Copy link
Member Author

Choose a reason for hiding this comment

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

こちらもPluginZip.build()に集約

@@ -0,0 +1,29 @@
---
sidebar_position: 1400
draft: true
Copy link
Member Author

Choose a reason for hiding this comment

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

draft: trueなのでローカルビルドでした表示されない

* @param stability "experimental" or "deprecated"
* @param message additional information
*/
export const setStability = <T = {}, U = {}>(
Copy link
Member Author

Choose a reason for hiding this comment

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

https://github.com/kintone/cli-kintone/pull/915/files#r1815855917 の対応

setStability(cmd, stability, msg) 関数を追加した。
ヘルプメッセージにStabilityが表示され、実行時に警告が出るようになる。


どこかのflagsにstabilityの情報を集約して、それに連動して表示が変わるようにしたかったが、yargsの仕組み上難しそうだった。

コマンドの生成を全てラップするヘルパー関数を置けば実現できるが、既存のレコード系のコマンドにも影響が出るので今回は個別のコマンドをラップする方式にした。

const cli = (pluginDir: string, options_?: Options) => {
// TODO: Reduce statements in this func
// eslint-disable-next-line max-statements
export const run = async (pluginDir: string, options_?: Options) => {
Copy link
Member Author

Choose a reason for hiding this comment

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

既存のレコード系のコマンドと合わせて関数名を run にした。

ref. https://github.com/kintone/cli-kintone/pull/915/files#r1815859115

Copy link
Member

Choose a reason for hiding this comment

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

Static Badge
めちゃ細かいんですが、ファイル名も(pack.tsとか?)機能に則したものの方が良さそうに思いました。

Copy link
Member Author

Choose a reason for hiding this comment

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

pack.tsにしました!

@tasshi-me tasshi-me marked this pull request as ready for review October 28, 2024 16:54
@tasshi-me tasshi-me requested a review from a team as a code owner October 28, 2024 16:54
@tasshi-me tasshi-me requested review from chihiro-adachi and shabaraba and removed request for a team October 28, 2024 16:54
Copy link
Member

@shabaraba shabaraba left a comment

Choose a reason for hiding this comment

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

@tasshi-me
いくつかコメントしました!
定義がわかりやすくて処理が追いやすかったです!

* Validate Manifest
* @param driver If set, also validate file existence and file size.
*/
validate(driver?: DriverInterface): Promise<ValidationResult>;
Copy link
Member

Choose a reason for hiding this comment

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

Static Badge

  • ManifestStaticInterface.loadJsonFileでdriverを渡している
  • ManifestInterfaceのメソッドでもdriverをしばしば引数で取る

ので、ManifestInterfaceのプロパティに入れてしまってもいいんじゃないかなと思ったのですがいかがでしょう?

もしくは、driverをメソッドごとに使い分けるユースケースが何かイメージありますでしょうか?

Copy link
Member Author

Choose a reason for hiding this comment

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

@shabaraba
これも悩んでいた部分ですね!
ManifestがDriverに依存しなくても成立する概念なので、Driverをプロパティに含めていませんでした!

直近は、
・マニフェストを読み込む場所
・マニフェストからファイルの実在を検証する場所
は一緒なので、プロパティに入れてしまっても問題ないと思います。

一方で、今後Driverを使い分けるケースとしては、以下のようなケースを想定しています。
・ZIPファイルやHTTPをソースとして受け付けてローカルにプラグインを生成するパターン
・Webエディタのようなオンメモリ→ZIPファイルを生成するパターン
・Web版plugin-packerのように入力ZIPファイルからプラグインZIPファイルを生成するパターン
 (ZipFileDriverは1つのZIPファイル内のファイル構造を表現しているので、入力・出力で2つのZIPファイルを扱う場合はDriverは2つ必要になります)


自分の考えなのですが、
ManifestInterface.validate()はManifestの形式的な妥当性だけを検証する
・Driverを使ったファイルの実在確認はContents.validate()を作成する
・ContentsはDriverに依存する(コンストラクタインジェクションする)
とすると見通しが良くなりそうです。

Copy link
Member Author

@tasshi-me tasshi-me Nov 2, 2024

Choose a reason for hiding this comment

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

(なんだかんだ言ってメインの利用ケースはLocalFSなので、デフォルト引数をLocalFSにしておいても良さそう)

/**
* Create a zipped contents using stream. Can be faster than createContentsZip above.
*/
export const _createContentsZipStream = async (
Copy link
Member

@shabaraba shabaraba Oct 30, 2024

Choose a reason for hiding this comment

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

Static Badge
こちらのメソッドは未使用のようですが、createContentsZipと比較するために用意している、という理解で良いでしょうか?
(あと今後もし使用するのであれば、exportしているのにアンダースコアから始まるのが少し気になりました)

Copy link
Member Author

Choose a reason for hiding this comment

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

Streamを使ったほうが速度的にもメモリ使用量的にも良さそうなんですけど、まだあまりちゃんと検証していないので置き換えずに置いているような状態です!
一旦はExportしない状態にしました!

/**
* Create plugin.zip from contents.zip
*/
public static async buildFromContentsZip(
Copy link
Member

Choose a reason for hiding this comment

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

Static Badge
contentsZipではcreateXxxというメソッド名だったので、どちらかの命名に統一できると良さそうに思いました。

またcontentsの方はzip.tsが切り出されているので、構造が(似せれるなら)似ているとよりわかりやすいかなと思いました。

Copy link
Member Author

@tasshi-me tasshi-me Nov 1, 2024

Choose a reason for hiding this comment

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

build/generate/createが散らばっているんですが、
一旦全てgenerate/generateFromに統一しました。
以下の方針で用語調整しました。

  • build: 複数の何かを組み合わせて何かにする系
  • generate: 新規に何かを生成する系(privateKeyなど)

createは上記2つに比べて、汎用で、かつCreativeなニュアンスも出そうなので、今回はなくしました

この辺りの単語選びはライブラリごとでも違うので悩ましい、、、
(fs.createReadableStream, crypto.generateKey など)

Copy link
Member Author

Choose a reason for hiding this comment

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

zip.tsの切り出しも行いました!

const cli = (pluginDir: string, options_?: Options) => {
// TODO: Reduce statements in this func
// eslint-disable-next-line max-statements
export const run = async (pluginDir: string, options_?: Options) => {
Copy link
Member

Choose a reason for hiding this comment

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

Static Badge
めちゃ細かいんですが、ファイル名も(pack.tsとか?)機能に則したものの方が良さそうに思いました。

Comment on lines 53 to 66
// 5. generate new ppk if not specified
const ppkFile = options.ppk;
let privateKey: PrivateKey;
if (ppkFile) {
logger.debug(`loading an existing key: ${ppkFile}`);
const ppk = await fs.readFile(ppkFile, "utf8");
privateKey = PrivateKey.importKey(ppk);
} else {
logger.debug("generating a new key");
privateKey = PrivateKey.generateKey();
}

/**
* Load JSON file without caching
*/
const loadJson = (jsonPath: string) => {
const content = fs.readFileSync(jsonPath, "utf8");
return JSON.parse(content);
};
const id = privateKey.uuid();
logger.debug(`id: ${id}`);
Copy link
Member

Choose a reason for hiding this comment

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

Static Badge
処理の順番に意味がもしなければ、// 7. package plugin.zipで再びこのあたりで定義した変数を利用するので、
// 6. prepare output directoryの後ろにこの処理群を持っていったほうが良さそうに思いましたがいかがでしょうか?

Copy link
Member Author

Choose a reason for hiding this comment

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

あざます!
処理順番を調整しました。

  1. 入力のバリデーション
  2. マニフェストの読み込み
  3. マニフェストの検証
  4. 出力ディレクトリの用意
  5. 秘密鍵の読み込み、指定されていない場合は生成
  6. プラグインのパッケージング
  7. watchモードの起動(指定されている場合)
  8. プラグインの書き出し

Copy link
Member Author

@tasshi-me tasshi-me left a comment

Choose a reason for hiding this comment

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

レビュー対応

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants