ラベル CI の投稿を表示しています。 すべての投稿を表示
ラベル CI の投稿を表示しています。 すべての投稿を表示

2023年5月28日日曜日

【GitHub Actions】Organization/Owner 配下にあるすべてのリポジトリをマトリックスにする

https://github.com/srz-zumix/github-actions-sample/blob/main/.github/workflows/owner_all_repo_matrix.yaml

name: Organization/Owner repo matrix
on:
  pull_request:

permissions:
  contents: read

env:
  GH_TOKEN: ${{ github.token }}

jobs:
  prepare:
    runs-on: ubuntu-latest
    outputs:
      repos: ${{ steps.get-repos.outputs.repos }}
    env:
      TARGET_OWNER: srz-zumix
    steps:
      - id: get-repos
        run: |
            # shellcheck disable=SC2016
            REPOS=$(gh repo list "${TARGET_OWNER}" --json nameWithOwner --template '[ {{ range $i, $e := .}}{{ if ne $i 0 }}, {{ end }}"{{ $e.nameWithOwner }}"{{ end }} ]')
            echo "repos=${REPOS}" >> "${GITHUB_OUTPUT}"
      - run: echo "${{ steps.get-repos.outputs.repos }}"

  main:
    runs-on: ubuntu-latest
    needs: prepare
    strategy:
      matrix:
        repo: "${{ fromJSON(needs.prepare.outputs.repos) }}"
    steps:
      - run: echo ${{ matrix.repo }} 

gh repo list でリポジトリをリストアップして、その結果を --template で json の配列に整形。
fromJSON で matrix にセットします。

gh 使うとこういったことが楽に実現できるので便利です。

今回は以上です。

2023年4月19日水曜日

【GitHub Actions】【reusable workflow / composite action】Enable Debug logging したときだけコンテキストをダンプする step を仕込む

 GitHub Actions の共通アクションやワークフローを書いていると、たまに失敗したときの状態をより詳しく知りたいことがあります。
今回はその一例として github コンテキストなど、GitHub Actions から提供されるコンテキストのデバッグログを仕込みたいと思います。

ところで GitHub Actions の VSCode 拡張が公式からリリースされました。
実はこれを使うとコンテキストやワークフローの候補が出るようになるので、大変便利になりました。
これによって、いちいちこのコンテキストからは何が参照できるんだっけな?と調べる必要が減りました。
※ event の詳細は 2023/4 時点では候補にでなかったので、まだまだ event の詳細は公式ドキュメント(webhook のドキュメントですが同じものが入ります)や実挙動を見て確認する必要がありそうです

ワークフローを書いてる最中はどういう変数があるかはわかりますが、実際にどのような値が入ってくるのかはドキュメントなどから想像するしかありません。
ローカル環境でワークフローを実行する nektos/act のようなツールもありますが、これらは非公式かつ挙動が完全一致するものではないので、実際にワークフローを動かして確認するのが現時点では一番確実です。

私は act の gh 拡張機能(gh-act)を開発しており、その動作確認をこめてコンテキストをダンプしてるので参考にしてみてください。


さて、ワークフローを開発している最中や、リポジトリ専用のワークフローであれば、なにか失敗したときの調査に役立ちますし、常にコンテキストをダンプする step を置いておけば良いかなと思ってます。(実際にそうしてることが多いです)

こんな感じです

    steps:
    - name: $github
      env:
        GITHUB_CONTEXT: ${{ toJson(github) }}
      run: |
        echo "${GITHUB_CONTEXT}"
  

一方、reusable workflow など共通化して多数のリポジトリから使用されるものの場合、機能とは関係のないダンプはいれづらいです。(気にしなくていいとも思ったりもしますが、なんか個人的には避けたかった)


GitHub Actions はワークフローが失敗したときにデバッグログを有効にして re-run できます。理想としてはデバッグログとしてダンプできたらいいなと思っておりました。


reusable workflow 側でデバッグログを有効にされていることをなんらかの方法で判別できればよかったのですが、環境変数やコンテキストでは判別できなさそうでした。
ただ、デバッグログを有効にした場合、最初に紹介した $github ステップの env の設定がダンプされていることに気づきました。

こんな感じ

そしてこの env の評価ですが、 if: false のように常に実行しないステップにしても評価はされました。


先程と同じ用に見えますが、前者は ✔ マークアイコンですが、後者は / マークでスキップされていることがわかります。

ここでようやく結論、タイトル回収です。
「if: false で常に実行しないステップを用意し、知りたい情報を env にセットしておく」
こうすることでデバッグログを有効にしたときだけ github コンテキストの内容を確認できました。この方法は github コンテキストに限らず使えます。


今回は以上です。


2022年10月18日火曜日

【GitHub Actions】コンテキストダンプのススメ

GitHub Actions では github や job などのコンテキストから git の状態や PR の内容、ジョブの情報などが取得できます。
これらを利用してステップの条件をつけたり、処理を変えたりなどができます。
さて、このコンテキストですがどういったものがあるのかは、ドキュメントで確認できます。

コンテキスト - GitHub Docs

ただ、実際にどういった値が入っているかまではわからないですし、ランナーやジョブによって当然値は変化します。
なので、コンテキストをダンプするための repository を用意しておくととても便利です。
私は ci-spec repository でいろいろなイベントトリガーでダンプできるようにしてあります。
https://github.com/srz-zumix/ci-specs/blob/master/.github/workflows/events.yml
この情報って取れるのかな?って探すことが結構あるので重宝してます。


また、github context の json は nektos/act の入力イベントとしても使えるので、常にダンプしておくと便利かもしれません。。かも。。

今回は以上。
act のことは「ブログズミ: nektos/act で GitHub Actions のワークフローをローカル実行」と「GitHub Actions のローカル実行ツール(nektos/act)を便利にする gh extension を作った」で書いたのでよければ見て下さい。

2022年9月13日火曜日

Dagger 使ってみた

Dagger とは?
Dagger は CI/CD パイプライン用のポータブルな開発キットです。
Dagger は他の一般的な CI/CD が YAML でパイプラインを記述するのと異なり、CUE で記述します。CUE については後述しますが、YAML よりプログラミング言語に近くて柔軟性が高いって感じですかね。

CUE によって YAML ではやりづらかったパイプライン再利用が容易になっています。
また、Dagger はローカルでも CI でも、どこでもパイプラインが実行できるのが特徴です。

Dagger はすべてコンテナ上で実行されます。コンテナが動く環境上であればどこでも「同じ」パイプラインを実行できるのが Dagger であり、CI/CD ツールではなく、パイプラインを共通化するレイヤーとして機能するツールです。

CUE
CUE は Configure, Unify, Execute の頭文字のようです。
CUE は JSON のスーパーセットで、CUE から JSON/YAML にエクスポートも可能です。

CUE については Dagger のページにも説明が詳しくあるのでそちらを参照してください。
https://docs.dagger.io/1215/what-is-cue/

CUE は YAML のマージ機能も備えているので↓みたいな使い方もできるみたいです。これはこれで便利そうですね。
CircleCI の設定ファイルを分割して CUE で合成してみたら割と簡単で便利そう - Mitsuyuki.Shiiba

今回は Dagger の話なので CUE そのものもそのうち触ってみたいです。

使ってみる
ものは試しで、使ってみました。
Dagger のサンプルとして todoapp があるのでそれでまずは動作を試してみるのがオススメです。このへんはありきたりな内容になってしまうので、省略します。
iutest に適用
iutest は筆者が書いてる C++ テスティングフレームワークです。
(まぁ最近はテスティングフレームワークの機能開発はほとんどしてないんですが・・いろんな CI サービスを使っている・使っていたのでそういう意味では参考になることもあるかもしれないです。)

今回 alpine イメージ上でのテストを今までしてなかったので、それを Dagger でやるようにしました。

ベースとなる cue ファイルはサンプルの todoapp を使いました。
1から書くよりもサンプルなどをベースに書いていくと楽だと思います。

なんですが、todoapp が参考にしたときと大分違う設定になっていました。
ちょうどそのころの Dagger 使った系の記事があったのでそちらを参考にしてください。
ベンダーロックインしないCI/CDパイプライン、Daggerを使ってCodeCheckを自動化してみた。

どういうふうに書いたかは百聞は一見に如かずということで、レポジトリを見てください。
この記事向けにコメントも追加してます。



とはいえ、見てくださいだけではこの記事の意味がないのでこの設定に至るまでの紆余曲折を記述しておきます。
変数展開は () でする
同じ設定はまとめたいので変数にしてたのですが、使うときに単純に変数を書くだけじゃだめでハマりました。
       // 必要な環境変数をセット
        env: {
            // string は () で囲んで展開する
            IUTEST_ROOT_DIR: (iutest_root_dir)
            // 文字列の中で変数展開する場合は ( をエスケープする
            IUTEST_OUTPUT_DIR: "\(test_result_dir)"
        }
exit: 0 は今の所意味がない
CTest が失敗しても後続の処理を継続したかったので終了コードを 0 に上書きしたいなーと思ったのですが、今はできないっぽい。
なので、しかたがないので script: contents の処理で失敗を無視してます。
always は condition の always ではない
↑と同じ理由で常に実行される処理を書きたかったので、always を使ってみたのですが、どうやらこれは実行条件の always とはちょっと違って、cache 利用するかしないかの always だったようです。
always を true にするとキャッシュを無視して常に実行されるようになりますが、依存処理が失敗していても実行するようなことはできませんでした。

https://docs.dagger.io/1231/always-execute/

常に実行したいってのは cache invalidate のことではないんだよなぁ・・

GitHub Actions で動かすには
dagger の cue ファイルを置いておいても、そのままでは CI サービスで実行されないので、各サービスでワークフローを書く必要があります。
GitHub Actions の場合は、dagger 用の action があるのでそれを使えばすぐに動かせます。
  dagger:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: dagger/dagger-for-github@v3
        with:
          cmds: |
            project init
            project update
            do ctest
    
CUE/Dagger を新たに覚えるのはつらい
ここから使ってみた感想なのですが、CUE が使いやすいかというとまだわからないのですが、少なくとも覚えることは多い印象。
YAML でのパイプライン記述における問題の1つである再利用性を CUE は解決していますが、最初に紹介した CUE を YAML のマージツールとして利用することで十分なような気もしますし、各 CI ツールで再利用性できる機能があったりしますし、Dagger である必要性があまり感じられませんでした。

より理解をするには CUE と Dagger の境界を認識して、それぞれで調べる力、検索力が必要になるかなと思いました。
ポータビリティについて
環境のポータビリティ
Dagger は「環境」のポータビリティを実現しています。
CI でもローカルでも同じ「環境」で処理を実行できます。

ローカルと CI で同じ「処理」をすることは Makefile でもなんでもいいですが、可能です。
なので CI と同じ「処理」をすることは Dagger を使わなくても可能です。
ただ、それだと実行環境は CI やローカルで異なるため、実行結果は変わってきます。
Dagger は実行環境もセットになっているので、同じ「環境」で同じ「処理」ができ、CI とローカルで同じ実行結果が期待できます。

これは大きなメリットです。仕事や個人開発でも CI でしか起きない問題の調査はめんどうです。ローカルで同じことができればこれも楽になります。
また、問題調査としてではなく開発者がローカルで動作確認をしたい場合に、ローカルで手軽に実行できるのも利点ですね。
私はゲーム開発に携わっているので、ターゲットプラットフォームでのビルドをローカルでしたいという需要はすごくわかります。(Dagger でゲーム開発のターゲットプラットフォームビルドができるかというと難しい気がしますが・・)

ただ、Dagger の実行環境はコンテナに制限されるため、コンテナでできないことはできません。
また、iutest はテスティングフレームワークなので、1つの同じ環境でテストするよりも、多様な環境でテストできたほうが嬉しいです。(※Dagger で複数環境用意するのもありですが、管理下の想定された環境よりも、管理外の環境のほうが意味があると思っている)
今回は alpine コンテナでのテストが今までなかったので Dagger を採用して GitHub Actions で動かしています(Dagger も環境の1つなので何かしらのテストを回しておきたいという意思)。
ワークフローのポータビリティ
ワークフロー?パイプライン?
言葉の定義があいまいなんですが、ここでは PR トリガーから結果の通知など CI の最初から最後までという意味合いでワークフローを使ってます。

「A PORTABLE DEVKIT FOR CI/CD PIPELINES」
Dagger のトップページにはこう書かれています。
パイプラインという言葉を使ってるので Dagger がカバーしている範囲はパイプラインと呼びます。

図にするとこんな感じかな。

Jenkins でジョブに直接処理を書かずに .sh ファイルとかにしようね。とか。ビルドツール使おうねとか。そららはパイプラインの話。
それのもう1つ上のレイヤーで環境とセットでまとめてくれるのが Dagger 。
さらに上のレイヤーであるワークフローはそれぞれ対応する必要がある。

Dagger はベンダー依存しない CI ツールという立ち位置ですが GitHub Actions での実行例を見ていただければ分かる通り、特定の CI サービス上で Dagger を実行するには Dagger だけでは完結しません。というか、GitHub Actions でいうとトリガー部分(on: pull_request)は Dagger では設定できませんし、動かす CI サービス固有の機能を使いたい場合は Dagger 外でやる必要があります。(Dagger はそういう CI の差を埋めてくれるものではないので)
そして CI サービスを引っ越しする場合には、トリガー周りなどそういった設定は書き直しになります。

CI/CD ワークフローのポータビリティという観点では、Dagger は直接的に貢献するわけではないです。(パイプライン部分だけでもポータブルになるので楽にはなる)
ただ、どのサービスを使うのか決まっているのであれば、そのサービスの書き方をしたほうが良いとも思えます。
逆に社内で使ってる CI サービスが多種多様であるとか、OSS だから手軽に乗り換えできると嬉しいとかであれば、Dagger を使う利点はあると思います。
ローカル実行について
実はローカル実行できる CI サービスもあります。
なので目的や事情によってはそのサービスのローカル実行機能を利用したほうがいい場合もあるかもしれません。
例えば CircleCI では cli からローカル実行できます。(制約はあります
GitHub Actions の場合、nektos/act というツールを使えばエミュレートできます。(act は大分できないことや、Hosted runner との差異がありますが・・)

これらで十分なのであれば Dagger に置き換える必要はないと思います。
例えば、act は GitHub Actions のイベントをエミュレートしてくれるのでワークフローのローカル実行が可能ですが、Dagger は step レベルのローカル実行しかできないです。
このへんは使い分けでしょうね。

まとめ
個人的には最近使ってみた Earthly の方が Dagger より使いやすいなと思いました。
Dagger がちょっと話題になりましたが、類似のツールと比較したり、今置かれている状況を踏まえて選択するのが良いと思いました。
以上、久しぶりに長めに書いた。ではでは。


2022年8月31日水曜日

nektos/act で GitHub Actions のワークフローをローカル実行

GitHub Actions で困る、というか面倒なのがワークフローのデバッグをするために都度 push してトライアンドエラーなところじゃないでしょうか?
単純に直列に step 並べるだけならそんなに困らないですが、steps.*.if 使ったり output 使って後続 step で利用しているような場合など、ちょっとしたミスで動かなかったりするのでできれば push するまえに確認できると嬉しいですよね。

あとはイベントによっては PR のときに確認できないことがあるので、マージしてからミスに気づくこともあります。
Release してみたらワークフロー失敗したってのは私も何回もやってます。そういう系は workflow_dispatch に対応しておくのがオススメ。

また、CI と同じことをローカルで実行したいということはよくあると思います。
CI サービスによってはローカル実行サポートしてることもありますが、GitHub Actions 公式には今の所ないので act を使います。

https://github.com/nektos/act

act pull_request とすると、 pull_request で trigger されるジョブが実行されます。
細かい使い方はドキュメント見ていただくとして、ここでは使ってみてわかった注意点などを書いておこうと思います。

最初に結論

最初にもっとも重要な注意点を書いておこうと思います。

act オススメしません!

補足すると「GitHub Actions と同じことをローカルでやりたい」のであれば act 使わずに Dagger とか Makefile とか shellscript とかなんでもいいので GitHub Actions のワークフローと処理を分離しておくことをおすすめします。
Jenkins のときと同じですね。

というわけでそのような目的がある場合は、この記事を読んでいないで処理の分離を始めましょう。

そうではなく、GitHub Actions のワークフローの方をローカルで検証したいときは act を使ってみるのはアリかもしれません。
記事の最後で私なりの利用ケースを考えてみたので興味のある方は最後までお付き合いいただけると幸いです。

ポイント
act の runner は hosted runner と同一ではない

act の runner は hosted runner よりも最小の環境で作られています。
なので hosted runner にはあるけど act の runner にはないものがあったりします。

より hosted runner に近いイメージも用意されていますが、とても大きいイメージなので注意してね、とのことです。
https://github.com/nektos/act#runners

↑にも書かれていますが、 -P ubuntu-18.04=nektos/act-environments-ubuntu:18.04 のように runs-on 指定の名前を置換してあげることができます。
このオプションを利用すると self-hosted runner 使っている場合の対応が簡単です。

act のときは〜をする・〜をしない

https://github.com/nektos/act#skipping-steps

やはりどうしても環境が異なっていたり、act でできないこともあり、act でそのまんまワークフローを実行するのは無理だったりします。
なので、そういう場合は if: ${{ !env.ACT }} のように ACT 環境変数で分岐させると良いです。

コンテキストの内容がすべて定義されない

act pull_request としても github context にはほとんどの情報が設定されません。
特に event は空っぽなので、 github.event.pull_request.head.sha とかを workflow 中に参照していると失敗します。
イベント情報などある状態で act 実行したい場合は、以下に書かれてるようにイベントの json ファイルをオプションで指定してください。

https://github.com/nektos/act#events

GITHUB_TOKEN は自動発行されない

https://github.com/nektos/act#github_token

はい。当たり前ですが自動では発行されないです。必要な場合は -s オプション使ってシークレットをセットしてください。

サービスコンテナは未対応

services の内容は無視されます。

設定ファイル

act で実行するにはそれなりにオプションで動くようにカスタマイズが必要だと思います。
お試し程度なら良いかもしれませんが、開発ワークフローで act を常用するようであれば、それらの設定をファイル(.actrc)に書き出しておくと良いと思います。
こうしておけば誰でも実行できるようになるはず。

https://github.com/nektos/act#configuration

ドキュメントに書かれてないこと
本家とは微妙に挙動が異なることがある

これはほんの一例ですが、公式ツールではないのでどうしても本家と違う挙動をすることがあります。
※下記の例は旧バージョンの話なのですでに修正されてます。

setup-ruby が ImageOS が想定外のために失敗する

act の提供してる image の ImageOS 環境変数が small ってなってて ruby/setup-ruby が失敗しました。どうやら setup-ruby は ImageOS 環境変数で実行環境を判断してるっぽいです。
step.*.env で ImageOS 環境変数を与えて上げること回避することはできますが、act 向けの変数になってしまうので微妙ではあります。

こんなときに便利かも
シークレットを設定する権限をもっていないとき

そういうケースってあんまりない気もしますが、なくもないのかなと思います。
シークレットが必要なワークフローの PR をしたけど、そのリポジトリのシークレットを設定する権限がない。 fork したとか、リーダーにしか権限ないとか?

シークレット追加してもらって検証というのもしづらいかなと思いますので、act -s で想定シークレットを渡してデバッグしておくといいかもしれません。

レアなイベントをトリガーにしている場合

pull_request イベントなら PR 出せば済む話ですが、workflow_dispatch とか release とか branch_protection_rule とかのイベントトリガーのワークフローをデバッグするのってめんどくさいです。
というのもイベントによってはデフォルトブランチにワークフローがあることが条件のものがあるからです。
ワークフローをトリガーするイベント - GitHub Docs

こういうやつ。

ですが、act 使えばこれらのイベントでトリガーされたときのデバッグが簡単になると思います。(env.ACT をみて dryrun な状態にしておくこと!)
最後に

act どうなんでしょうね?
本当に必要なケースってあんまりないような気もしてしまいます。

GitHub Actions のワークフローで書くことって大概が pull_request イベントだと思うし、それなら実際に動かしたらいいってなるし。

時間かかるからローカルがいい、処理をデバッグしたいって話だとワークフローとは別の話な気がするので act でなくても解決できるはず。

デフォルトブランチに入れなきゃ動作確認できないイベントはたしかに act があると便利そうではありますが・・果たして本当に楽になるのだろうか?


「デフォルトブランチに入れなきゃ確認できない」って部分は GitHub 公式でなんらか解決策を出してくれると嬉しいですね。

以上。

2022年8月9日火曜日

GitHub Actions の Composite Action で post 処理を実現する方法

GitHub Actions での処理の共有方法として action がありますが、現在この action は javascript と docker そして composite の  3  つの方法で作成することができます。
筆者は今から action 作るなら composite をおすすめします。
composite action は登場した当初は runs.steps[*].if や runs.steps[*].uses が使えなかったので、ちょっと力不足でしたが最新のバージョンであればこれらが使えるようになっており、action を作る上で困ることはほとんどなくなったと思います。

じゃあ、タイトルはなんなんだということになりますが、ちょっと凝ったことしようと思うと(他ではできるけど) composite ではできないこともあります。

それがタイトルに書いた post 処理です。
右のスクリーンショットは action に書ける Metadata syntax なのですが、composite だけ post に対応してません。(詳細はリンク先へ)


でも、大丈夫です。というのがこの記事。
いずれ公式で composite action にも post が対応されると思いますが、今の状態でも post 処理できます。


その前に。
post 処理とはどんなものかと言うと、ジョブのステップが全部終わった後に行う処理のことです。みなさんがよく使うであろう actions/checkout でも post 処理が行われています。

こんな感じ。
基本的には action で設定したものをもとに戻したり、docker コンテナを停止したりするのに利用されています。


では本題です。
composite action で post 処理を行うには・・・
post 処理ができる action を uses で呼び出す」ことで可能です!

つまり、「composite action は uses で他の action を呼び出せるので、javascript/docker action を呼べば良い」のです。

リポジトリが別になっちゃう?
いえ、大丈夫。 uses は相対パスで action を呼び出せます。

つまりこういうことです。

composite action の repository のサブディレクトリに javascript/docker action を配置して、それを composite action から呼び出し、呼び出した action の post 処理を composite action の post 処理の代わりにします。
「uses: "./resources/post-action"」 がその部分で、この action のメイン処理は空で、post 処理で起動したコンテナの終了をしています。

実際にこの書き方をした action のリポジトリはこちら。
https://github.com/srz-zumix/setup-service-jenkins


composite ではない action を使うことになるので、それはそれで問題があったりしますがネストされた action なので実はそのへんもなんとかなっちゃうかもしれないなと思ってます。(javascript action の default node version 問題とか)
(docker action は実行できない os があるので、この目的ではあまりオススメしません)


ざつにざーっと書きましたが、今回は以上となります。では。


2022年5月27日金曜日

AppVeyor で cygwin setup に失敗するようになったので対応した

2022/05/20 ごろから AppVeyor で Cygwin のセットアップが失敗するようになりました。

Starting cygwin install, version 2.900
User has backup/restore rights
Current Directory: C:\cygwin/var/cache/setup
Could not open service McShield for query, start and stop. McAfee may not be installed, or we don't have access.
root: C:\cygwin system
Selected local directory: C:\cygwin/var/cache/setup
net: Preconfig
site: http://cygwin.mirror.constant.com/
mbox Parse Errors:  line 12: The current ini file requires at least version 2.903 of setup.
Please download a newer version from https://cygwin.com/setup-x86.exe
unattended_mode is set at mbox: returning default value
site: http://cygwin.mirror.constant.com/
mbox Parse Errors:  line 12: The current ini file requires at least version 2.903 of setup.
Please download a newer version from https://cygwin.com/setup-x86.exe
unattended_mode is set at mbox: returning default value
site: http://cygwin.mirror.constant.com/
mbox Parse Errors:  line 12: The current ini file requires at least version 2.903 of setup.
Please download a newer version from https://cygwin.com/setup-x86.exe
unattended_mode is set at mbox: returning default value
site: http://cygwin.mirror.constant.com/
mbox Parse Errors:  line 12: The current ini file requires at least version 2.903 of setup.
Please download a newer version from https://cygwin.com/setup-x86.exe
unattended_mode is set at mbox: returning default value
site: http://cygwin.mirror.constant.com/
mbox Parse Errors:  line 12: The current ini file requires at least version 2.903 of setup.
Please download a newer version from https://cygwin.com/setup-x86.exe
unattended_mode is set at mbox: returning default value
download/verify error in unattended_mode: out of retries
note: Installation incomplete.  Check C:\cygwin\var\log\setup.log.full for details
Ending cygwin install

issue も出てます。対処方法もそこでコメントされている通りで、最新の setup exe を上書きダウンロードして使用すれば OK です。

https://github.com/appveyor/ci/issues/3820

Powershell であれば issue のリンクのように書けば対応できます。
64bit 版は setup-x86_64.exe をダウンロードして C:\cygwin64\setup-x86_64.exe に保存します。
https://github.com/appveyor/build-images/blob/master/scripts/Windows/install_cygwin.ps1#L10-L13

Powershell 以外であれば curl で下記のようにダウンロードすれば大丈夫です。

      curl -sSL -o C:\cygwin\setup-x86.exe "https://cygwin.com/setup-x86.exe"
      curl -sSL -o C:\cygwin64\setup-x86_64.exe "https://cygwin.com/setup-x86_64.exe"

今回は以上。


2022年4月26日火曜日

Jenkinsfile がでかすぎてエラーになる場合の対処方法

 Jenkinsfile に記述してる処理が多すぎて以下の例外が発生してしましました。

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during class generation: Method code too large!

java.lang.RuntimeException: Method code too large!
	at groovyjarjarasm.asm.MethodWriter.a(Unknown Source)
	at groovyjarjarasm.asm.ClassWriter.toByteArray(Unknown Source)
	at org.codehaus.groovy.control.CompilationUnit$17.call(CompilationUnit.java:827)
	at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1065)
	at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
	at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
	at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
	at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
	at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:142)
	at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:127)
	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:571)
	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:523)
	at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:337)
	at hudson.model.ResourceController.execute(ResourceController.java:97)
	at hudson.model.Executor.run(Executor.java:429)

これは Groovy (Java) の 64kb 上限にかかったために発生した Exception です。
https://stackoverflow.com/questions/40049917/jenkins-pipeline-script-fails-with-general-error-during-class-generation-metho
method のサイズが大きすぎるのが問題なので、pipeline 以下に直接記載されている処理を別 method に切り出して、pipeline からは呼び出すだけにしたりしてサイズを削減してみてください。
SharedLibrary に切り出してもいいですし、ジョブを分ける方法もあると思います。

なんにせよ分割することで対応することになると思います。
今回は以上。では。

2022年3月24日木曜日

GitHub Actions だけで Jenkinsfile の lint をする

 皆さん、 Jenkins 使ってますか?
私は仕事で使ってます。最近は GitHub Actions が使えるようになったので、脱 Jenkins を進めているのですが、まだまだ Jenkins とのお付き合いは続きそうな感じです。

ところで近年の Jenkins に久しぶりに触れているのですが、昔と大分変わってきた印象があります。
そのなかでも私は as Code に注力をしていっています。
Jenkinsfile を使ったジョブの定義は当然のことですが、JCasC (Jenkins Configuration as Code) を使った Jenkins そのものの as Code をしています。あとは JobDSL も使ってます。(もう GUI でぽちぽちしてジョブ作るのがしんどいなと思うようになってしまった)JCasC も JobDSL も便利なんでぜひ使ってほしいところですが、今回は Jenkinsfile の話です。

パイプラインの Validate

as Code をすると PR 出してレビューしてもらって、履歴も管理しやすいしとっても便利です。
さて、PR を出したとき Jenkinsfile の動作確認はどのようにしていますか?
もちろん「PR ブランチを指定してジョブを実行する」これでもいいです。
しかし、カッコの閉じ忘れだったり、しょうもない typo で時間を無駄にしてしまうことはないでしょうか?

そういうときは jflint が便利です。
Jenkins 2.0 (5): Jenkinsfileをコマンドラインからlintする - 生産性向上ブログ
Jenkins にはパイプラインの Validate してくれる API が備わっていますが、jflint はその呼出を簡単にできるようにしてくれたものです。(できれば公式の jenkins-cli.jar が対応してほしい)
jflint 自体は Jenkins の API を実行しているだけなので、Jenkins のインスタンスが必要になります。
通常は使っている Jenkins のインスタンスを挿せば問題ないです。
というか、そうでないと利用しているプラグインがインストールされていなくて Validate が失敗したりしてしまいます。

さて、ここで表題に戻ります。
GitHub Actions だけで Jenkinsfile の lint をする」
jflint を使った方法は Jenkins のインスタンスが必要ですが、ここでは利用している Jenkins には到達できない、もしくは汎用的・テンプレート的なリポジトリで対になる Jenkins インスタンスが存在しないと過程して GitHub Actions のみで lint します。
(※Jenkins インスタンスがあって到達可能ならそれ使ったほうがいいです)

GitHub Actions に Jenkins を起動する

GtiHub Actions ではサービスコンテナの機能があります。
テストするために DB など他のサービスがほしい場合に便利な機能です。

これを利用して Jenkins を起動し、サービスコンテナの Jenkins に Validate してもらいます。(Jenkins は使いますが GitHub Actions だけで完結します。Jenkins 使わずに Validate するのは相当しんどい。プラグインがあるしカバーしきれない…)

サービスコンテナは↓な感じで起動できます。
セットアップウィザードを無効にしないと入力待ちで止まってしまうので、このオプションは必須です。
起動したコンテナのIDは「job.services.サービス名.id」で取れるのでこれを使って steps などで操作することもできます。

    services:
      jenkins:
        image: jenkins/jenkins:lts-jdk11
        credentials:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
        env:
          # セットアップウィザードを無効
          # disable setup wizard
          JAVA_OPTS: -Djenkins.install.runSetupWizard=false
        ports:
          - 8080:8080
          - 50000:50000
  

上記例では起動したコンテナに localhost:8080 でアクセスできるので、この URL で jflint を実行すると Jenkinsfile の lint が GitHub Actions だけでできるようになります。(※これだけじゃならない)

プラグインをインストールする

さて、ここで1つ問題が発生します。起動した Jenkins はプラグインが空っぽで Validate すらできない状態になってしまっています。

デフォルトプラグイン、推奨プラグインをインストールする必要があります。
さらに、Validate する Jenkinsfile によっては追加でプラグインのインストールが必要です。
プラグインのインストールは jenkins-cli.jar の install-plugin で可能なので、これをサービスコンテナの Jenkins に対して実行すればインストールできます。

java -jar jenkins-cli.jar install-plugin -s http://localhost:8080 ws-cleanup

こんな感じですね。サービスコンテナから jenkins-cli.jar をダウンロードして実行するか、コンテナに対して exec すればできると思います。

setup-service-jenkins アクション

さて、GitHub Actions で Jenkins を起動して jflint することができそうなことはわかりました。しかし、プラグインのインストールが必要でちょっとめんどくさいです。
なので、アクションにしてみました。

https://github.com/srz-zumix/setup-service-jenkins

サービスコンテナの記述はそれぞれ必要になりますが、コンテナ ID を指定してこのアクションを実行すると必要なプラグインを Jenkins にインストールするのと、 jenkins-cli のラッパースクリプトを agent にインストールします。

      - uses: srz-zumix/setup-service-jenkins@main
        with:
          id: "${{ job.services.jenkins.id }}" # サービスコンテナの ID (job.services.サービス名.id)
          port: 8080 # ポート番号(サービスコンテナのポート設定と合わせる)
          install_suggested_plugins: true # Suggested Plugins をインストールするかどうか
          plugins_file: JenkinsPlugins.txt # 追加でインストールしたいプラグインのリストファイル
  
公式イメージからのセットアップ

例えば公式のイメージを起動した場合はプラグインが空っぽなので、install_suggested_plugins オプションを true にしてデフォルト推奨プラグインをインストールするか、プラグインが列挙されたファイルを plugins_file に指定してインストールしてください。
デフォルト推奨プラグインはこちらのファイルに列挙したものになっています。
(Suggested Plugins をインストールした状態から cli でダンプ、加工したもの)
https://github.com/srz-zumix/setup-service-jenkins/blob/main/resources/DefaultJenkinsPlugins.txt

公式イメージを使う場合はセットアップウィザードを無効にすることを忘れないでください。
現状アクション側で対応してないので、冒頭に書いたようにサービスコンテナを起動するときのオプションが必須です。

カスタムイメージからのセットアップ

例えば、実際に使用している Jenkins のベースイメージがあり、プラグインなどセットアップ済みであれば特にプラグインのインストールは不要になると思います。
おそらく公式イメージよりも都合がよいと思うのでこちらのほうがおすすめですが、クリーンな状態からテストしたい場合などは公式イメージを使うほうがおすすめです。
適宜選択してください。

jenkins-cli.jar のラッパースクリプト

このアクションを使用すると agent マシンにラッパースクリプトの jenkins-cli をインストールします。こちらはサービスコンテナの Jenkins を挿すようにしただけのラッパーです。
CLI でそこそこ自由に Jenkins を操作できるのでワークフローを作る際に使ってみてください。

GitHub Actions だけで Jenkinsfile の lint をする

最終的にできあがったワークフローはこちらです。
https://github.com/srz-zumix/github-actions-sample/blob/main/.github/workflows/reviewdog-jflint.yml

公式イメージ + suggested plugins だと ansiColor プラグインがインストールされないので、jflint で指摘されているのがわかりますね。

今後の展望

サービスコンテナで Jenkins が起動し、プラグインインストールや CLI での操作が可能になりました。今後は JCasC をロードさせて Jenkins の設定を読み込ませた状態でジョブやスクリプトを実行してみたいです。
また、Shared Library のテストが書け、実行できると思っているのでそのへんも手を付けたいです。

以上。


2022年2月17日木曜日

gcc -fanalyzer が実行しきれる CI サービスを求めて・・・

 先週書いた記事の続き
ブログズミ: メモリ不足で gcc が kill される場合になんとかビルドする

上記記事の対応で CircleCI 上でいくつかメモリリークなどの検知がされたのですが、誤検知を無視したりコード修正したりしてエラーが出ない状態にしていったものの、テストコードのビルドが最後まで完了しきらない状態に陥ってしまいました。

状態としては、無出力タイムアウトが発生していたので CircleCI の no_output_timeout を延ばして回避しようとしました。
しかし、5時間とかにしても一向に終わらない。。
エラー(警告)が出ない状態であれば ggc の設定を緩和しても kill されることはなくなったので、コンパイル速度優先の設定にしても無出力タイムアウトしてしまいダメ。

長いタイムアウト設定で何度もトライアンドエラーしてるとクレジット消費に悪影響が出るので、一旦 CircleCI を諦めて他のサービスを検討することにしました。

なるべくリソース豊富はところ、かつビルド時間が無料プランの制限を圧迫しないものを探しています。
各サービスのリソース状況はこちらのリポジトリで調べたものを参考にしています。
https://github.com/srz-zumix/ci-specs
拙著にも記載してます。(宣伝)
https://srz-zumix.booth.pm/

以下、随時更新していきます。

1. GitHub Actions (kill)
2. CircleCI (no output timeout)
3. RazorOps (kill)
4. AzurePipelines (timeout 360min)


2022年2月10日木曜日

メモリ不足で gcc が kill される場合になんとかビルドする

Process completed with exit code 137.
g++: fatal error: Killed signal terminated program cc1plus
compilation terminated.
上記のようなエラーで gcc が終了した場合、実行環境のメモリ不足が原因の場合があります。
このような場合どうしたらよいのでしょうか?

正解は「メモリを増やす」です!


・・・ですが。
そうはいかない場合もありますよね。特に筆者は CI サービスを無料の範囲で使っているので、実行環境のスペックには制限があり、増やすことが難しいです。

それでも、それでもビルドがしたい。

・・・ので無理やりがんばります。

並列数を減らす
単純な話ですが make などで並列してる場合は並列数を減らしましょう。

ガーベージコレクションの設定を調整する
--param ggc-min-heapsize

上記のコンパイラーオプションを使うことで、コンパイラーの GC (ガベージコレクション)の設定ができます。
それぞれどういう設定かの
ggc-min-expand は % 単位で、ヒープ拡張できる最小の割合。
RAM が 1GB 以上あれば 100% がデフォルト、それ以外の場合は 30% を下限に設定される。
ggc-min-heapsize は GC 開始する最小のヒープサイズ。この値が小さいと GC 頻度が上がる。デフォルトは 4MB〜128MB の間で RAM サイズや RLIMIT の数値で決定されるもよう。

ggc-min-expand/ggc-min-heapsize 両方を 0 にすると常に Full GC することになる。
これらの値を調整することで、少メモリな環境でもビルドできるようになる。
ただし、時間はめちゃくちゃかかる
片方(ggc-min-expand)0 だけでも相当時間かかってタイムアウトしてたので、無料 CI 環境では厳しい。

gcc -fanalyzer をやりたくて ggc の調整してたけど、時間かかりすぎて終わらない・・
https://github.com/srz-zumix/iutest/pull/564
もうちょいスペック高い CI を検討してみる。



2022年1月20日木曜日

GitHub Actions の action 開発者にお願いしたいメジャーバージョンアップするタイミング

 GitHub Actions とっても便利ですね!
個人開発ではもちろんのこと、会社でも便利に使っています。
使うだけではなく action を作ったりもしてます。

さて、本題に入りますが、
会社の GitHub が Enterprise のため github.com の方にはあるが Enterprise にはまだない機能や環境を使われると action が動かないことがあります。
幸い使用する action のバージョンを固定することで回避できるのですが、できることならそのような変更時にはメジャーバージョンアップしてほしいなと思ってます。
(SemVer 採用してる前提ですが)メジャーバージョンでバージョン固定しているケースが多いため、マイナーバージョンアップだと管理下の全リポジトリに対してバージョン固定をして回らないといけなくてすごく面倒くさいのです。。
メジャーバージョンアップならこのような破壊的変更を自然に避けられるので、何卒。
(まぁ Enterprise 使ってないとそういった事情はわからないので仕方がないとは思ってますけど)

実際にあった例としては、

  • 「using: "composite"」
    Composite Action が Enterprise でまだ使えなくて動かなくなった。
  • 「using: "node16"」
    Enterprise はまだ「docker」か「node12」しか使えない状態だったので動かなくなった。(こっちは Enterprise のアップグレード以外に方法があるなら知りたい)
がありました。
とりあえず using 変えると Breaking Change になるようにするのが良さそうですね。

この辺を自動で対応するなら using の差分があったらラベルつけるとかできればなんとかなりそう。(actions/labeler だとファイル単位なので別のやり方が必要)
なんかいい方法見つけたらブログで書きたいと思います。

以上。

2021年12月6日月曜日

CircleCI の Concurrency と Parallelism

この記事は「CircleCI Advent Calendar 2021のカレンダー | Advent Calendar 2021 - Qiita」の6日目です。

CircleCI が無料プランで 30 同時実行可能になったので、Parallelism との関係を調べてみました。

Parallelism とは?

CircleCI ではワークフローのジョブとジョブはそれぞれ並行実行されます。
参考:ワークフローを使用したジョブのスケジュール - CircleCI#ワークフローの構成例 

一方、Parallelism はジョブの中の処理を並列実行する仕組みです。
参考:テストの並列実行 - CircleCI

Parallelism はジョブの steps をそれぞれのワーカーで同じように実行されますが、各ワーカーに付与される CIRCLE_NODE_INDEX 環境変数の値(0,1,2...)でテストを分割したり条件分岐できます。
この Parallelism はプランによって使用できる上限が決まっています。
筆者の場合は今月頭の時点で 16 でした。

さて、ここで少し疑問がわきました。
16 parallelism のジョブを 2 つ使ったら 30 同時実行されるのでしょうか?

Parallelism を含むジョブを 30 以上実行したらどうなるか?

筆者が CI サービスのまとめをしてるリポジトリで検証してみました。

まとめルートリポジトリ:https://github.com/srz-zumix/ci-specs
同時実行の関連まとめ:https://github.com/srz-zumix/ci-parallel

ジョブの開始・終了時刻を記録、その情報から json を生成して chrome://tracing で可視化しています。
この方法は以前「ブログズミ: chrome://tracing で並列処理の可視化をしてみたらすごく便利だった話」で詳細に書いてますので、そちらを参照してください。
ジョブ設定はこちらを参照してください。
https://github.com/srz-zumix/ci-parallel/blob/master/.circleci/config.yml

16 parallelism x 2 job

16 -> 16 という感じでジョブは同時実行されませんでした。
続いて Parallelism を減らし、ジョブ数を増やしてみます。

4 parallelism x 8 job

今度は 28 -> 4 という感じで実行されました。
組み合わせたらダメとうわけではないようです。

(1 parallelism x ) 31 job

最後に Parallelism なし(1)を 31 job です。

当然ですが、30 -> 1 のように実行されました。

まとめ

Parallelism の数分だけ空きがないとそのジョブはキュー待ちする
同時実行数に収まるように Parallelism 数を決めると良さそうですね。
※この挙動に関しては 2021/12/05 時点での結果であり将来的に変わる可能性はあります。

以上。

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年9月14日火曜日

GitHub Actions Composite Action で uses が使えるようになった!

GitHub Actions: Reduce duplication with action composition | GitHub Changelog

GitHub Actions では Composite Action でワークフローの一部を1つのアクションとしてまとめ共有できることができます。
複合実行ステップ アクションの作成 - GitHub Docs

GitHub Actions は YAML のアンカー・エイリアスに対応しておらず、 Azure Pipelines のような Templates 機能もありませんが、この機能で Action に切り出すことで似たようなことができます。
Composite Action は Docker や Javascript Action と違い、通常のワークフローの記述と近いかたちで書くことができますので、よりアンカー・エイリアスや Templates と近い感覚で記述ができます。

**近い**としたのは Composite Action で書けることは通常のワークフローよりも制限がされているからです。
uses もその1つでした。
今回のアップデートで uses が使えるようになり、checkout アクションや python / node / ruby などの setup 系アクションを含んだ Composite Action を書けるようになったので、かなり便利になりました!

(個人的には shell を動的に解決したいとか conditional (if) を使いたいとかはありますが、uses が対応されたことで大分使い勝手が良くなったので嬉しい)


2021年9月3日金曜日

GitHub Actions でペアな値のマトリックスを組む

 CI でパラメタライズドなテストを実行するときに、マトリックスを組むことがあると思います。
GitHub Actions でも strategy.matrix でマトリックスを組めます。

例えば、上記公式ドキュメントのサンプルの

strategy:
  matrix:
    node: [10, 12, 14]
steps:
  # Configures the node version used on GitHub-hosted runners
  - uses: actions/setup-node@v2
    with:
      # The Node.js version to configure
      node-version: ${{ matrix.node }}

↑こちらは node-version が 10,12,14 のステップがそれぞれ実行されます。合計で 3 回です。

さらに、因子を追加して例えば

strategy:
  matrix:
    node: [10, 12, 14]
    expect: [ "dubnium",  "erbium", "fermium" ] 

とすると、以下のような組み合わせになります。

101214
dubnium10,dubnium12,dubnium14,dubnium
erbium10,erbium12,erbium14,erbium
fermium10,fermium12,fermium14,fermium

node と expect の因子の直行になります。合計は 3x3 の 9 回です。
ただ、このような組み合わせではなく、ペアな因子1つを作りたい場合もあります。
上の例では [10, dubnium], [12, erbium], [14, fermium] という組み合わせにしたいです。
その場合は、以下のように include を使って書くとスマートそうです。

strategy:
  matrix:
    include:
      - node: 10
        expect: dubnium
      - node: 12
        expect: erbium
      - node: 14
        expect: fermium      
strategy:
  matrix:
    node: [10]
    expect: ["dubnium"] 
    include:
      - node: 12
        expect: erbium
      - node: 14
        expect: fermium
 

前者は include のみで記述、後者は matrix に include で組み合わせを追加しています。
この例では前者のほうがきれいに見えますが、一部の組み合わせだけ値が異なる場合は後者の方法で書いたほうがきれい書けける場合もあります。

実例

今まで1つの値に複数の値をもたせたりしてたのですが、とてもきれいに書き直せました。


こちらはサンプルの前者の方法と同じで、include で必要な組み合わせを書いています。


https://github.com/srz-zumix/ci-yaml/blob/e1e1d6d15bb75f9682bc05304e7ec61162de094b/.github/workflows/search.yml
こちらはサンプルの後者と同じ方法で、 path が "" の場合は matrix で、空白以外の場合は include で組み合わせを追加しています。


今回は以上です。では。

2021年8月3日火曜日

【JFrog Pipelines】Cron Trigger を設定する

 しばらく活動してなかったら Subscription キャンセルされてしまったので Cron Trigger で何もしないジョブを定期実行するようにしました。

ちなみにキャンセルされるとその環境を継続利用するにはプランのアップグレードをするしかないようです。
もし、無料プランで使い続けたい場合は同じメールアドレスでの登録はできないので、別のメールアドレスを用意して新規登録する必要があります。

本題に戻りましょう。
Cron Trigger はリソースに cron 定義を追加し、それを input にすることで設定できます。
CronTrigger - JFrog - JFrog Documentation

とっても簡単です。
今回の内容は以上ですが、環境が使えなくなると1から Integration/Pipelines Source/Node Pool などなどを構築しなおしになるので、この設定をしておくと良いと思います。

では。

2021年7月15日木曜日

【技術書典11】 CI サービス本の増補・改訂版をリリースしました

 7/10(土)から技術書典11が始まってます
弊サークル虎空棘魚からオンラインマーケットにて、「あつまれCIサービス」の増補・改訂版である「2021夏」を販売してます。
また、既刊「詳解Integromat」も販売中です。
よろしくおねがいします!




2021年7月7日水曜日

[Azure Pipelines] DockerHub pull rate limit に対応する

これらのつづき

Azure Pipelines の場合は以下を参考に「Project Settings」の「Service connections」を開き、「Docker Registry」を追加すれば OK です。
Registry Type に DockerHub があるので、それを選択して、ID/パスワード(トークン)をセットします。
Service connections in Azure Pipelines - Azure Pipelines | Microsoft Docs

今回は以上。

2021年6月28日月曜日

JFrog Pipelines はじめました

 Shippable はだいぶ前に JFrog 傘下になり JFrog Pipelines と Shippable の2つのサービスが提供されていました。
Shippable のサービス提供も続けていくよとされていましたが、とうとう終了となりました。
(マイニングの影響もあったのかはわからないけど、あれは困ったものですな)
The Next Step in the Evolution of Shippable: JFrog Pipelines

いつまで見られるかわからないですが、こちらは引越し前の Shippable ビルド履歴です。
https://app.shippable.com/github/srz-zumix/iutest/dashboard/history
5/3 まで元気に動いてました。お疲れ様でした。

さて、Shippable は終了となりましたが、JFrog Pipelines に移行できるようなのでやってみました。
移行するのは以下のリポジトリです。
https://github.com/srz-zumix/iutest

Pricing

その前に気になるのはお値段ですよね。
Shippable のときは↓な感じでしたが、

Unlimited builds for public projects
150 builds/month for private projects
Forum support

(Shippable がどんなのだったかは拙著「あつまれCIサービス」を読んで頂くのもありですよ)

JFrog Pipelines はこんな感じ。

ビルド時間無制限はこのご時世ではもう無理なんでしょうねぇ
それでも2000分/月使えるのはありがたいです。(Travis CI も毎月付与にならないかなぁ)

プランの確認ができたので、早速登録して使ってみましょう。

Get Started

Start for free などからリンク開くと以下のようなページが開きます。

日本語ページもあるのでそちらからも登録できます。
クラウドプロバイダー(Select your cloud provider)
クラウドプロバイダーの選択が出てきて、ちょっと本当に無料の範囲でできるのかな?と不安になりますが、No Credit Card だし大丈夫だと信じて進みます。
(実際問題ない)
自分はどれもあまり詳しくないのですが、まだ多少知ってるという理由で Google Cloud を選択しました Google 選んだつもりでしたが AWS を選んでました(2021/08/02 追記)。

サーバーの詳細(Server Details)

お客様詳細情報(Create your Credentials)
メールアドレスとパスワードを記入します。
パスワードは大文字・小文字、数字、記号を含める必要があります。

ユーザー詳細(User Details)
氏名を入力します。英語(アルファベット)で記入する必要があるようです。

PROCCED して完了。

問題がなければ「JFrog Free Subscription Activation」というタイトルでメールが来ます。
「Click here to activate your JFrog subscription」のリンクを開いてアクティベートします。

待ちます。

完了したらログインできるようになるので Login しましょう。
ログインしたら↓のようなダッシュボードが開くと思います。
セットアップ

JFrog には Pipelines の他にもプロダクトがありますが、今回使うのは Pipelines です。

まずは左側メニューから「Pipelines」を選択。「Clik to Activate」をクリック。

待ちます。

君はそのページ見れないよ。とエラーっぽいメッセージが出ますが、admin なはずなのでそんなわけはありません。
おそらくまだセットアップ中なのでしょう。待ちます。

・・・zzz

一晩寝かせたことでアクセスできるようになってました。(少し時間がかかると思ったほうがよさそうですね)
※一度ログアウトしてログインし直すと見えるようです(2021/08/02 追記)
Pipelines が使えるようになったので設定の続きをしていきます。


JFrog のドキュメントに「QuickStart Guide: JFrog Cloud - JFrog - JFrog Documentation」があるのでそちらを参考に進めます。
今回は Pipelines だけまずは使いたいので Step 2/3 はスキップして「Step 4: Define a pipeline」から始めます。
Artifactory を Integrations に追加
※成果物を特に扱わない、パイプラインを試してみるだけ、という場合は飛ばして OK

先に、Artifactory 用の API Token を JFrog の User Profile から払い出しておきます。
右上のユーザーメニューから「Edit Profile」を開き、ログインパスワードを入力して Unlock します。
Unlock すると操作できるようになるので「Authentication Settings」の「Generate API Key」をクリックします。
API キーが生成されたら、コピーしておきましょう。

つづいて、「Administraion」タブの「Pipelines」から「Integrations」を開き、右上の「+ Add an Integration」をクリックします。
Pipeline から利用するので「Usage」は Pipelines を選択。
名前は任意、「Integration Type」に Artifactory を選択します。
URL と User はデフォルトのままで良いと思います。
API Key に先程コピーしたものをペーストし、「Create」をクリックして完了です。

「Assign Pipelines to this Integration」はとりあえず Any で OK です。制限かけたい場合はチェックを外すと許可する source を選択できます。(画像にはいくつか source がありますが、現時点ではまだ source 登録してないので空っぽだと思います)
GitHub を Integrations に追加

次に GitHub を Integrations に追加します。
Artifactory と同様に、右上の「+ Add an Integration」をクリックします。
Pipeline から利用したいので「Usage」は Pipelines を選択。
名前は任意、「Integration Type」に GitHub を選択します。
最後に GitHub のパーソナルアクセストークンを作成して入力したら「Create」ボタンを押します。

Node Pool にノード追加

次に実行環境を用意しておく必要があるので登録します。
「Administraion」タブの「Pipelines」から「Node Pools」を開き、右上の「+ Add Node Pool」をクリックします。
下記画面のようになるので、名前の入力とイメージを選択します。
選択可能なイメージは Ubuntu/CentOS/Windows があります。

Node Limits は同時に起動可能なノード数の制限です。1 にした場合、このノードを使うジョブは 1 つずつ順番に実行されます。

Node Idle Interval はノードが停止するまでの時間です。
ノードは常に起動しているのではなく必要なときに起動します。
commit でジョブを実行する場合、インターバルが短いと都度都度ノードを起動することになるので、使い方に合わせて時間を調整しましょう。
ちなみに、有料プランでは静的ノードが使えます。


Pipeline source を追加

ノードの準備ができたらパイプラインを登録しましょう。
「Administraion」タブの「Pipelines」から「Node Pools」を開き、右上の「+ Add Pipeline Source」をクリック、「From YAML」を選択します。

パイプライン YAML を PR で追加したいので、「Multi Branch」を選択します。
「SCM Provider」は上で追加した GitHub のインテグレーションを選びます。
ほどなくリポジトリが選択可能になるので、目的のものを選択。
「Exclude/Include Branch Pattern」で YAML の Sync をするブランチの対象を制御できます。
最後に、YAML ファイルのパスを入力して「Create Source」しましょう。
(JFrog では YAML ファイルは任意の場所におけます。)

この時点ではまだ YAML がないので Sync は失敗します。

Pipeline を記述

パイプラインを記述します。
ドキュメントや、サンプルプロジェクトがあるのでそちらを参考にすると良いと思います。

移行後の iutest の YAML はこちら
https://github.com/srz-zumix/iutest/blob/master/jfrog-pipelines.yml


他の CI サービスとちょっと使い方に特徴があるので、その点だけ説明します。

チェックアウトパス

他の CI サービスではソースとなるリポジトリがカレントディレクトリにチェックアウトされることが多いと思いますが、JFrog Pipelines は複数リポジトリをソースにできるので、それぞれのワークスペースにチェックアウトされます。
このパスは「res_{{ resource_name }}_resourcePath」環境変数で取得できるので、ディレクトリを移動してからビルドやテストを行いましょう。

シークレット環境変数

環境変数は「Generic Integration」を追加することで使用できます。
こちらも上記チェックアウトパスと同様に「int_{{ integration_name }}_{{ env_name }}」のような環境変数になっているので注意してください。

例:https://github.com/srz-zumix/ci-specs/blob/1f64ac66f635b6ffeee06db45ae1210bf0fd1c64/jfrog-pipelines.yml#L28

GitHub ステータス更新もパイプライン記述が必要

他の CI サービスでは自動的に GitHub のコミットステータスを更新してくれますが、JFrog Pipelines ではパイプラインに明記しないといけません。(仕組み上しかたがないですが)
やり方は簡単で、「update_commit_status {{ resource_name }}」で現在の execution の状態に合わせてステータスを更新してくれます。
より細かな制御も可能です。詳しくはドキュメントを参照してください。
Sending Build Status to Source Control - JFrog - JFrog Documentation

Sync

パイプラインをコミットしたら Pipeline Sources で Sync が成功するか確認しましょう。
「Pipelines」>「Pipeline Sources」を開き、Status を確認してください。
パイプラインの記述に不備がなければ「Success」になっているはずです。
問題がある場合は一番右のログボタンから何が原因か確認して修正しましょう。

パイプライン実行

Sync できたらいよいよ実行可能です。
PR トリガーは Sync が成功したあとから有効になるので、最初は手動でトリガーするか、空コミットを push するかで起動しましょう。
(パイプライン修正 PR をして修正されたパイプラインで動作を見たいときも同様。改善したい)

手動でトリガーする場合は、「My Pipelines」から実行したいパイプラインを選択し、そこからトリガーするステップを開いて実行するだけです。

結果は履歴から確認できます。

Next

ここまでで JFrog Pipelines でジョブを実行できるようになったと思います。
JFrog Pipelines は他の CI サービスと使い勝手が少し違います。
Jenkins など他の CI と連携したり、複雑なジョブを構築したりしていくことができるようです。ドキュメントがまとまっているのでそちらを参考に挑戦してみてください。
https://www.jfrog.com/confluence/display/JFROG/Get+Started

バッジ

CI サービス恒例のバッジですが、残念ながら見つけられませんでした。
バッジを付ける方法が見つかったら、このブログで紹介します。

最後に

Shippable が終了したのは残念でしたが、JFrog Pipelines で同じように CI できそうです。
また、Shippable のころに使いこなせなかった Assembly Line が使えるようになって、ドキュメントって大事だと改めて気付かされました。

今回は以上。ではでは。