こんにちは。なっしゅです。
今取り組んでいる作品でドット絵をGitHub上にあげていますが、その枚数を計算してREADME.md
に自動的に表示する機構を作る機会があったので備忘録として残します。
したいこと
- ドット絵をdot-worksディレクトリにpushする。
- GitHub Actionsのworkflowが実行される。
- C++をコンパイル、実行し
dot-works
内の.png
の枚数を${COUNT}
として取得する。 -
README.md
に${COUNT}
を書き込む。
実装
まず1つ目の目標として「push時にC++をコンパイル、実行する」ところまで実装します。
.github/workflows/.yml
を作成します。
name: Write the number of dot works down on README.md
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install g++
run: sudo apt-get install g++ -y
- name: Compile C++ program
run: g++ counter.cpp -o counter
- name: Run C++ program
run: ./counter
dot-works
ディレクトリ内のドット絵の枚数(=.png
の枚数)、を数えるC++のコードは以下の通りです。
#include <iostream>
#include <filesystem>
int main() {
const std::string path = "dot-works";
int count = 0;
for (const auto& entry : std::filesystem::recursive_directory_iterator(path)) {
if (entry.path().extension() == ".png") {
++count;
}
}
std::cout << count << std::endl;
return 0;
}
実行したところ、どうやら<filesystem>
はC++17の環境で動作するようです。
よって、.yml
を以下のように書き換えました。
name: Write the number of dot works down on README.md
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install g++
run: sudo apt-get install g++ -y
- name: Compile C++ program
run: g++ counter.cpp -o counter -std=c++17
- name: Run C++ program
run: ./counter
pushしたら上手くいきました。
では次にREADME.md
に書き込むように.yml
をいじっていきます。
name: Write the number of dot works down on README.md
on: [push]
jobs:
update-readme:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: 'main'
- name: Install g++
run: sudo apt-get install g++ -y
- name: Compile and Run C++ Program
run: |
g++ counter.cpp -o counter -std=c++17
./counter > output.txt
- name: Update README
run: |
COUNT=$(cat output.txt)
README_CONTENT=$(cat README.md)
echo -e "${README_CONTENT}\n今までで**${COUNT}**つのドット絵作品が描かれています。" > README.md
- name: Commit and Push if Changes
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add README.md
git commit -m "Update README with .png file count" -a || echo "No changes to commit"
git push
これはファイルの末尾に文字列を追加する場合のコードです。
echo
では-e
オプションをつけていますが、これは\n
を含めたエスケープシーケンスを有効にするためのオプションです。また、echo
のあとの文字列をシングルクォーテーションで囲ってしまうと${COUNT}
が変数ではなく文字列として認識されてしまうので注意してください。
最後に、READMEの好きな場所に文字列を挿入することを考えましょう。
sed
コマンドで文字列を挿入する位置を定めるため、README.md
の文字列を挿入したい場所に次のようにコメントを書きます。
<!-- PNG_COUNT_START -->
<!-- PNG_COUNT_END -->
このように書くことによって文字列を追加、ではなく更新することができます。
sed
コマンドを使って.yml
を次のように書き換えます。
name: Write the number of dot works down on README.md
on: [push]
jobs:
update-readme:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: 'main'
- name: Install g++
run: sudo apt-get install g++ -y
- name: Compile and Run C++ Program
run: |
g++ counter.cpp -o counter -std=c++17
./counter > output.txt
- name: Update README
run: |
COUNT=$(cat output.txt)
sed -i "/<!-- PNG_COUNT_START -->/,/<!-- PNG_COUNT_END -->/c\<!-- PNG_COUNT_START -->\n今までで**${COUNT}**つのドット絵作品が描かれています。\n<!-- PNG_COUNT_END -->" README.md
- name: Commit and Push if Changes
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git diff --quiet && git diff --staged --quiet || (git commit -am "Update README with .png file count" && git push)
これで文字列を任意の場所に挿入することができました。
以上です。
ファイル階層
.
├───.github/
│ └───workflows/
│ └───.yml
├───dot-works/
└───counter.cpp