理系学生日記

おまえはいつまで学生気分なのか

GitLab CI/CDでMarkdownファイルをdocxファイルに変換し、Generic Packages Repositoryにアップロードする

手動でいちいちpandocを実行するのは面倒です。 Merge Requestの作成やそのbranchに変更が入ったタイミングで、Markdownファイルをdocxファイルに変換し、リポジトリにアップロードしたい。

実際にこれを実装すると、以下のようにMerge Requestに紐づく形でファイルがアップロードされます。

CI/CD設定

gitlab-ci.ymlに関しては何の捻りもありません。

docx:
  stage: release
  image:
    name: pandoc/ubuntu:2.14.2
    entrypoint: [""]
  script:
    - apt update && apt install -y curl
    - utility/release-docx.sh
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - "**/*.md"

利用したコンテナイメージはpandoc/ubuntuというPandocの公式イメージです。 Ubuntuベース以外にも、Pandocのイメージにはalpineベースのpandoc/coreもあります。 後述するスクリプトをashで書くのに慣れていないので、今回はUbuntuベースを選択しました。

単にPandocのコンテナイメージから、utility/release-docx.shを呼び出すだけですね。

docx変換・アップロードスクリプト

release-docx.shは以下のようになります。 このスクリプトで、Markdownファイルからdocxファイルへの変換、Generic Packages Repositoryへアップロードを行います。

#!/bin/bash
set -eux

# 再帰的にMarkdownファイルをdocxに変換する
function md2docx {
    local destdir=${1?"missing dest dir"}

    find doc -name \*.md | while read md; do
        # 先頭の "doc/" を削除し、/ を - に置換
        # ex.) doc/xxxx/001.md -> xxxx-001.docx
        local docxname=$(basename $(echo ${md#doc/} | tr / -) .md).docx

        pandoc \
            --from=markdown \
            --to=docx \
            --output="$destdir/$docxname" \
            --reference-doc=doc/custom-reference.docx \
            --resource-path="$(dirname $md)" \
            $md
    done
}

# 指定したディレクトリ配下のdocxファイルをGeneric Packages Registryにアップロードする
function upload_docx {
    local dir=${1?missing dir}
    local url="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/$(echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME | tr / -)/0.0.1"

    find $dir -name \*.docx | while read docx; do
        local filename=$(basename $docx)
        curl \
            --header "JOB-TOKEN: $CI_JOB_TOKEN" \
            --upload-file $docx \
            "${url}/$filename"
    done
}

WORK_DIR="${HOME}/${CI_MERGE_REQUEST_ID}"
mkdir -p $WORK_DIR

md2docx $WORK_DIR
upload_docx $WORK_DIR