2022年6月29日水曜日

【DockerHub】typo して間違った repository に push してしまった Docker image を正しい repository にコピーした

docker に push する先を typo してたまま CI 回しててしばらくずっと間違ったところに push してました。

oneapi が正しかったのに openapi ってなってました。
ここで今までビルドしたイメージを openapi から oneapi の方に移したいなと思ったのですが、これをやる場合 openapi から pull して oneapi に push するだけではあるのですが、すべてのタグでやるのはめんどくさかったのでスクリプトにしました。


#!/bin/bash
# usage: docker-cp-repo.sh src_repo dst_repo
set -euo pipefail
SRC_REPO=$1
DST_REPO=$2
SRC_TAGS=$(curl -s https://registry.hub.docker.com/v1/repositories/${SRC_REPO}/tags | jq -r '.[].name')
DST_TAGS=$(curl -s https://registry.hub.docker.com/v1/repositories/${DST_REPO}/tags | jq -r '.[].name')
ONE_SIDE_TAGS=$(echo -e "${SRC_TAGS}\n${DST_TAGS}" | sort | uniq -u)
SRC_ONLY_TAGS=$(echo -e "${SRC_TAGS}\n${ONE_SIDE_TAGS}" | sort | uniq -d)
for t in ${SRC_ONLY_TAGS}; do
echo $t
docker pull "${SRC_REPO}:$t"
docker tag "${SRC_REPO}:$t" "${DST_REPO}:$t"
docker push "${DST_REPO}:$t"
done
deleteTags() {
docker images | grep "$1" | awk '{print $2}' | xargs -I{} docker rmi $1:{}
}
# deleteTags "${SRC_REPO}"
# deleteTags "${DST_REPO}"
./docker-cp-repo.sh srzzumix/openapi-cxx srzzumix/oneapi-cxx

のように使います。
jq 使うと repository のタグ一覧が簡単に取れるので便利です。
今回は以上。では。

2022年6月24日金曜日

Jenkinsfile の checkout gitSCM で LFS Pull のタイムアウト設定

【Jenkins】ERROR: Timeout after 10 minutes - コガネブログ

hudson.plugins.git.GitException: Command "git lfs pull origin" returned status code 143:

ゲーム開発してると git lfs においてるファイルが大きくなりがちで、タイムアウトで取得失敗することもあるかと思います。
そういう場合は↑のブログにある通り、チェックアウトのタイムアウトを延ばせば解決します。
これは git lfs pull が checkout の拡張として実装されているからです。
https://javadoc.jenkins.io/plugin/git/hudson/plugins/git/extensions/impl/GitLFSPull.html

Jenkinsfile の場合は以下のようにします。
CloneOption にも timeout 設定がありますが、これはその名の通り clone するときのタイムアウトなので git lfs pull には効果ありません。

1
2
3
4
5
6
7
8
9
10
11
12
checkout(
    scm: [$class: 'GitSCM',
        extensions: [
            [$class: 'GitLFSPull'],
            [$class: 'CheckoutOption', timeout: 30],
            [$class: 'CloneOption',
                timeout: 30,
            ],
            ...
        ],
    ]
)

大分前に調べたのですが、すっかり忘れてたので備忘録として残しておきました。

2022年6月7日火曜日

Jenkinsfile の sh ブロックの shellcheck をする GitHub Action をリリースしました

https://github.com/srz-zumix/jenkinsfile-shellcheck

actionlint が run の内容に対して shellcheck してくれるのをみて、Jenkinsfile の sh にもしてほしいなと思って作ってみました。

一応それっぽくできたのですが、何点か既知の問題があります。

sh ブロックの検出は AstBuilder 使ってるので問題ないのですが、行継続のエスケープが展開されて一行になるので、行番号がズレてしまうのが問題です。

ちなみに上は Groovy の文字列の記述がどう展開されるかテストしたものです。
Groovy の文字列記述には複数種類があります。ダブルクオーテーション・シングルクォーテーション、それを3つつなげて複数行記述。「$/」と「/$」で囲うことでも複数行記述できます。このうちシングルクォーテーション以外は GString にあたります。($/~/$はエスケープがそのまんま展開されるのがダブルクオーテーションと異なります)

GString は「${HOGE}」のような変数を展開します。
Jenkinsfile で GString の場合に環境変数を参照する場合に ${env.HOGE} のように書くこともあるのではないでしょうか。
(GString は知らないと結構ハマりやすいところだと思います)

AstNode から getText すると GString は展開されて取得できるのですが、そのとき「${env.HOGE}」は「env.HOGE」として展開されます。
この挙動はそんなには問題ないですが、Jenkinsfile が実行されるときのそれとは異なるので注意。


実行時と異なるという点での問題はまだあります。
sh の引数には単一の文字列ではなく、文字列連結して渡すことも当然できるため以下のようなケースで正しく解析できません。

頑張ればできないことはないかもしれませんが、今は非対応です。

ちなみに GString でシークレット環境変数を使うと展開されてから評価されるので shell 実行時に環境変数展開されるようにすべきなのですが、その警告は Jenkins がしてくれるので jenkinsfile-shellcheck ではノータッチです。
(ジョブ実行時もしくは validate で検出可能)

issue や pull request お気軽にどうぞ。
では、今回は以上です。