2021年10月29日金曜日

Docker な Jenkins でプラグインインストール済みイメージを作る

 表題の件は検索すればすぐ見つかる内容ですが、古い方法のほうが検索上位に来ることが多いのでこの記事を書きました。

旧方式(install-plugins.sh)

プラグイン名や、プラグインが列挙されたテキストファイルを渡すとインストールしてくれる shell スクリプトが Jenkins のベースイメージに入っているのでそれを使います。

COPY JenkinsPlugins.txt plugins.txt
RUN /usr/local/bin/install-plugins.sh < plugins.txt

plugins.txt の中身は以下のように「プラグイン名:バージョン」となっています。

analysis-model-api:10.3.0
ansicolor:1.0.0
antisamy-markup-formatter:2.1
apache-httpcomponents-client-4-api:4.5.13-1.0
authentication-tokens:1.4
authorize-project:1.4.0
badge:1.8

この方法は既に Deprecated です。
https://github.com/jenkinsci/docker/blob/master/README.md#install-plugins-script-deprecated

一部プラグインがインストールできないなくて、調べたことがきっかけで新方式を知りました。
実際にはツールの問題じゃなく、lts イメージを使ってたのが直接の原因でしたが。
Some plugins failed to download! Not downloaded とエラーになる場合は、lts-jdk11 のイメージを使いましょう。

新方式(jenkins-plugin-cli)

新しい方法は CLI を使います。CLI を使って操作するのが現在の主流のようです。
https://github.com/jenkinsci/docker/blob/master/README.md#plugin-installation-manager-cli
この CLI はベースイメージに入っているので追加インストールとかは不要です。

COPY JenkinsPlugins.txt plugins.txt
RUN jenkins-plugin-cli --plugin-file plugins.txt

plugins.txt の中身は install-plugins.sh のときと同じで大丈夫です。
プラグイン列挙ファイルを渡す場合は --plugin-file(-f) を使います。
オプションの詳細は README を参照してください。
https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options

インストールされているプラグインリストを取得するには以下のようにすれば可能なので、イメージを起動後に手動でプラグインをインストール後、docker exec とかでコンテナに入ってコマンドを実行してください。

$ jenkins-plugin-cli --list

Installed plugins:
ace-editor 1.1
analysis-model-api 10.3.0
ansicolor 1.0.0
antisamy-markup-formatter 2.1
apache-httpcomponents-client-4-api 4.5.13-1.0
authentication-tokens 1.4
authorize-project 1.4.0
.
.
.
workflow-job 2.41
workflow-multibranch 2.24
workflow-scm-step 2.13
workflow-step-api 2.24
workflow-support 3.8
ws-cleanup 0.39

Bundled plugins:

All requested plugins:

Plugins that will be downloaded:

Resulting plugin list:
ace-editor 1.1
analysis-model-api 10.3.0
ansicolor 1.0.0
antisamy-markup-formatter 2.1
apache-httpcomponents-client-4-api 4.5.13-1.0
authentication-tokens 1.4
authorize-project 1.4.0
.
.
.
workflow-job 2.41
workflow-multibranch 2.24
workflow-scm-step 2.13
workflow-step-api 2.24
workflow-support 3.8
ws-cleanup 0.39
Done

ただ、この出力をそのまま --plugin-file として渡せないのでスクリプトコンソールで出力したほうが手っ取り早いかもしれません。
その場合は下記のようなスクリプトを実行することになると思います。

def plugins = jenkins.model.Jenkins.instance.getPluginManager().getPlugins()
plugins.each {
    println ("${it.getShortName()}:${it.getVersion()}")
} 
最後に

今回はプラグインの事前インストールでしたが、Jenkins の Docker イメージ使ってちょっとやってみたいことがあるので進展がありましたら、またブログにしたいと思います。
では。

2021年10月22日金曜日

npm-groovy-lint + reviewdog で Jenkins Shared Library の PR チェック

 reviewdog は様々なツールの出力から PR に対してレビューをつけてくれるとても便利なツールです。私も GitHub Actions で reviewdog 使って shellcheck とか lint とかをよくかけています。

今回は Jenkins Shared Library の groovy スクリプトの lint をしたいと思い、npm-groovy-lint + reviewdog の GitHub Actions を用意したので紹介します。

reviewdog とツールがセットになったアクションがたくさんありますが、
npm-groovy-lint のアクションはなかったので作るか、アクション側で書くかのどちらかになります。
今回はアクション側で対応したいと思います。

.reviewdog.yml

reviewdog は .reviewdog.yml に runner 情報(実行コマンドや出力フォーマット)を書いておくと、-runners オプション指定で簡単に実行できるようになるので、その方法を使います。

作成した .reviewdog.yml がこちらです。

runner:
  npm-groovy-lint:
    # cmd: npm-groovy-lint # (required)
    cmd: npm-groovy-lint -o log.txt && cat log.txt
    errorformat: # (optional if you use `format`)
      - '%-P%f'
      - '%*\s%l%*\s%tnfo%*\s%m'
      - '%*\s%l%*\s%tarning%*\s%m'
      - '%*\s%l%*\s%trror%*\s%m'
      - '%-Q'

コマンド指定のところで一度ログファイルに出力しているのは、色付き出力されたものを reviewdog に認識させるのが面倒だったためです。

github/workflows/reviewdog.yml

続いて、GitHub Actions のワークフローです。
こちらは npm-groovy-lint を実行する環境を整えつつ、reviewdog を実行するワークフローになっています。

name: GitHub Actions - reviewdog
on:
  pull_request:

jobs:
  groovylint:
    runs-on: ubuntu-latest
    container:
      image: docker://nvuillam/npm-groovy-lint
      credentials:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}
    steps:
      - run: apk add curl git
      - uses: reviewdog/action-setup@v1
      - uses: actions/checkout@v2
      - name: Run reviewdog
        env:
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          reviewdog -reporter=github-pr-review -runners=npm-groovy-lint

npm-groovy-lint を実行するのに、公式のコンテナ上で実行するのが楽だったのでそのようになっています。このコンテナには reviewdog が実行するために必要になる curl と git が入ってなかったので、はじめに追加をしてます。

結果

これでセットアップ完了です。
以下のように npm-groovy-lint の結果をレビューコメントしてくれるようになりました。



2021年10月14日木曜日

「自分リリースノート」を一年書いてみた

 GitHub のユーザープロフィールページで自分リリースノートを書いています。
毎月リリースでその月にやったこととかをまとめているのですが、それが書き始めて一年以上経ったので振り返り。

KPT
Keep

継続した
あのころに何をしていたのか振り返られるのが良い

Problem

当初ほどの情熱がない
定形的な情報の入力が面倒くさい

Try

ある程度の自動化をしたい
マンネリ化してるのでその他の欄をもう少し書きたい

最後に

このブログももうすぐ10年ですが、それと同じくらい続けられたいいですね。
ではでは。

2021年10月8日金曜日

2021年10月1日金曜日

Tails of Words v0.3.0 リリース

シルバーウィークに久しぶりに連休を取ったので Tales of ARISE をやってました。まだクリアしてません。もうちょいでクリアだと思うのですが。なので最近はゲームばっかりしてます。

はい。では本題です。

tails-of-words 0.3.0 をリリースしました。
tails-of-words は「ブログズミ: CEDEC でやってた表記ゆれ検出をお試し実装してみた」で作成した表記ゆれ検出ツールです。
(なんだか某ゲームっぽいツール名ですね)

今回は前回ブログ時点からの差分を紹介したいと思います。

変更履歴
knp 対応

まず大きな変更点として knp(pyknp) に対応しました。
knp は juman の出力を入力に係り受けとかを解析してくれるものですが、
tails-of-words では knp の固有表現検出機能を使いました。

固有表現検出機能を使うと以下のように「奈良先端科学技術大学院大学」を1つの単語として検出できるようになります。


knp を有効にするには --knp オプションを付けます。実行環境に knp がインストールされている必要があるので、knp インストール済みの tails-of-words の docker container を使うのが楽だと思います。

コンフィグファイル対応

tails-of-words のオプション及び評価関数のパラメータをファイル指定できるようにしました。

log: DEBUG
html2test: True
exclude_ascii: True
exclude_alphabet: True
jaro_winkler: True
knp: False

# スコア計算の設定値
score_config:
  # 読みが同じ時にかける値
  same_yomi_scale: 1.2
  # 出現数の差の正規化数([0,1])にかける値
  occurrences_sacle: 1.0
  # 読みが同じかつ、長音が消えてる場合にかける値
  same_yomi_with_remove_long_vowel_scale: 0.8
  # 片方を内包し、末尾の長音の差分のみの場合にかける値
  diff_only_long_vowel_scale: 1.2
  # 片方を内包している場合にかける値
  inclue_other_one: 0.5
  
形態素解析のための正規化による表記ゆれ吸収問題を解決

pyknp で knp/jumanpp の出力する際に特定の文字列が出力フォーマットと衝突し、正しくパースできないので(たとえば半角スペースや @ などの記号)、解析前に全角文字に変換したりしているのですが、これにより当該文字の半角・全角の表記ゆれ検出ができないようになっていました。

これに対応するために、pyknp の結果の形態素の見出し(midasi)から正規化した文字をもとに戻す処理をいれました。
また固有表現検出に対応したことで「2021 年秋」と「2021 年秋」のようなスペースのゆれも検出できるようになりました。(スペース含んだ固有表現と認識されればの話)

jaro_winkler 編集距離に対応
レーベンシュタイン距離がデフォルトですが、ジャロ・ウィンクラー距離にも対応しました。
--jw,--jaro-winkler オプションを付けると切り替わります。
tails-of-words では編集距離を 0-1 の値に正規化して評価していますが、この値が変わるので表記ゆれの検出結果にも変化がでます。
0=不一致 1=一致


XML入力に対応
Blogger のバックアップ出力が xml だったので、このブログを解析するために対応しました。
xml ファイルの場合は text が解析対象になります。

標準入力に対応
パイプでつなげて処理したい。curl で html 取ってきて解析させたい。ということで対応。
以下のように --stdin-type で html を指定すれば html2text した文字列で解析できます。
curl -fsSL https://srz-zumix.blogspot.com/2021/09/cedec.html | tails-of-words --stdin-type html swing --exclude-alphabet --exclude-ascii -t 1 -
ASCII のみやアルファベットのみを除外するオプションを追加
記号のみやアルファベットのみの形態素は未定義語の hinsi_id になるようなので、
tails-of-words swing -i 6 hoge.txt のように -i オプションで解析対象の品詞を名詞(6)のみにすることで除外できます。(デフォルトは 名詞(6) と 未定義語(15))

GET と Get や get など大文字小文字の揺れを除外したい場合、これで実現可能だったのですが、未定義語にはカタカナ語なども入ることがあるため、このユースケースに対応するために --exclude-alphabet (--no-alpha) と --exclude-ascii (--no-ascii) オプションを追加しました。
最後に
とりあえず実装してみた前回バージョンからだいぶパワーアップしました。
実際に拙著やこのブログの表記ゆれを検出しようと使ってみたら、こうなりました。
編集距離にはまだ他の手法もあるようなので、そのうち対応してみたいです。

今回は以上。