diff --git a/.github/workflows/md2html.yml b/.github/workflows/md2html.yml index b0ea865..6696835 100644 --- a/.github/workflows/md2html.yml +++ b/.github/workflows/md2html.yml @@ -6,27 +6,43 @@ jobs: convert_via_pandoc: name: Convert via Pandoc runs-on: ubuntu-24.04 + permissions: + contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 2 - name: create CHANGED_FILES list + id: changed # https://stackoverflow.com/a/57862507/11480802 # https://docs.github.com/ja/actions/reference/environment-variables - # .md の変更がないとこの行で失敗するので注意 - run: git diff --name-only ${GITHUB_SHA}^..$GITHUB_SHA | grep -e ".*\.md" > CHANGED_FILES + # 対象を md/ep*.md に限定しないと、CLAUDE.md や README.md だけの変更で + # entrypoint.sh が md/epREADME.md.md.tmp を探しに行き pandoc が落ちる + run: | + git diff --name-only "${GITHUB_SHA}^..${GITHUB_SHA}" \ + | grep -e "^md/ep.*\.md$" > CHANGED_FILES || true + if [ -s CHANGED_FILES ]; then + echo "found=true" >> "$GITHUB_OUTPUT" + cat CHANGED_FILES + else + echo "found=false" >> "$GITHUB_OUTPUT" + echo "md/ep*.md の変更が無いので変換をスキップします" + fi - uses: ./ + if: steps.changed.outputs.found == 'true' env: FDL_KEY: ${{ secrets.FDL_KEY }} - - name: Commit files + - name: Commit and push + if: steps.changed.outputs.found == 'true' + env: + BRANCH: ${{ github.ref_name }} run: | git config --local user.email "action@github.com" git config --local user.name "GitHub Action" - git add html/*.html - git add md/*.md - git add chapters/episodes.yml + git add html/*.html md/*.md chapters/episodes.yml + if git diff --cached --quiet; then + echo "コミットする変更が無いので終了します" + exit 0 + fi git commit -m "update html by GitHub Action" - - name: Push changes - uses: ad-m/github-push-action@master - with: - github_token: ${{ secrets.GITHUB_TOKEN }} + git push origin "HEAD:$BRANCH" diff --git a/CLAUDE.md b/CLAUDE.md index 260743f..d8a6c10 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -79,7 +79,37 @@ PY なお `html/ep60.html` / `ep62.html` / `ep65.html` は対応する md と内容がずれている (md 更新後に再生成されていない)。手元での再現結果が合わなくても、それが原因のことがある。 +## ワークフロー (md2html) の癖 + +**CHANGED_FILES は tip コミットの差分しか見ない。** `git diff ${GITHUB_SHA}^..${GITHUB_SHA}` +なので、`md/ep.md` を**最後のコミットに含めないと変換されない**。ep68 追加の後に +CLAUDE.md のコミットを重ねたせいで、ep68 の HTML が生成されずに終わった実例がある。 +md を追加したコミットは push 時の先頭に置くか、後続コミットを重ねないこと。 +(マージコミットは第一親との差分になるので、master へマージした時点で拾われる) + +変換対象の grep は `^md/ep.*\.md$`。以前は `.*\.md` と緩く、`CLAUDE.md` や `README.md` +だけを変更すると `md/epREADME.md.md.tmp` を探しに行って pandoc が落ちていた (run #320)。 + +`md/ep*.md` の変更が無い push では、変換とコミットをスキップして正常終了する。 +以前はこの場合 grep が空振りしてジョブごと失敗していた (run #313/#314/#316/#322)。 + +生成物は `github.ref_name` へ push するので、feature ブランチでも完走する。 +以前は `ad-m/github-push-action` が常に `master` へ push しようとして +`! [rejected] HEAD -> master` で必ず失敗していた。 + +## MP3 のチャプター付け + +`chapters/add-chapters.sh` (既定で最新1件、`--all` で全件)。音声の場所は `AUDIO_DIR`、 +既定はリポジトリと同じ階層の `finished_audio`。詳細は `chapters/README.md`。 + +`add-chapters.py` は `episodes.yml` と `cover_art.jpg` を**相対パスで開く**ので、 +直接呼ぶ場合は `chapters/` に `cd` してから。ラッパーはこれを吸収している。 + +`episodes.yml` は Actions 生成物なので、新しい回を処理する前に master を pull すること。 + ## その他 - URL 短縮 (Firebase Dynamic Links) はサービス終了に伴い `entrypoint.sh` で無効化済み -- ワークフローは push 時に走るが、`.md` の変更が1つも無いと CHANGED_FILES 作成の行で失敗する +- Docker イメージは `pandoc/latex:2.6` (Alpine 3.9、EOL 済み) のまま。今は動いているが、 + Alpine のミラーが消えた時点で壊れる。その際は runner に pandoc を直接入れる形へ移行する。 + その場合も **`--wrap=none` を必ず付ける**こと (付けないと既存の出力と数十文字ずれる) diff --git a/chapters/README.md b/chapters/README.md index b5b4b05..b2b8310 100644 --- a/chapters/README.md +++ b/chapters/README.md @@ -1,5 +1,44 @@ -# add-chapters.py +# add-chapters + +MP3 にチャプターとメタデータ (タイトル・アートワーク) を付ける。 + +## 準備 + +```sh +pip3 install -r requirements.txt +``` + +## 使い方 + +```sh +chapters/add-chapters.sh # finished_audio 内の最新 MP3 1件だけ +chapters/add-chapters.sh --all # ファイル名に old を含むものを除く全件 +``` + +音声の置き場所は `AUDIO_DIR` で変えられる。既定はリポジトリと同じ階層の `finished_audio` +(`show-notes` と `finished_audio` が並んでいる従来の配置を想定)。 + +```sh +AUDIO_DIR=/path/to/mp3 chapters/add-chapters.sh +``` + +個別に実行したい場合は、`chapters/` に移動してから `add-chapters.py` を直接呼ぶ +(`episodes.yml` と `cover_art.jpg` を相対パスで開くため、CWD が `chapters/` である必要がある)。 + +```sh +cd chapters && python3 add-chapters.py /path/to/68.mp3 +``` + +## 注意 + +- MP3 のファイル名は `68.mp3` / `19.5.mp3` のように**エピソード番号のみ**である必要がある。 + この番号で `episodes.yml` を引く。 +- `episodes.yml` は `../md/ep*.md` を元に GitHub Actions が生成する。 + 新しい回のチャプターを付ける前に、**最新の master を pull しておくこと**。 +- タイムスタンプの無い見出し (「お知らせ」など) はチャプターにならない。 +- 実行すると `add-chapters.py` が該当回に当たるまで全エピソードを標準出力に吐くが、 + デバッグ出力なので無視してよい。 + +## 出典 - Forked from [rui314/add-chapters.py](https://gist.github.com/rui314/6e435fcebe3998333d37904e893c8c12). -- `../md` を元に GitHub Actions で `episodes.yml` が作られるので、その後 `add-chapters.py` を実行することで MP3 にチャプターを付けることができる。 -- MP3 のファイル名は現状 `1.mp3` のような形式のみ受け付ける。 diff --git a/chapters/add-chapters.sh b/chapters/add-chapters.sh new file mode 100755 index 0000000..591c59f --- /dev/null +++ b/chapters/add-chapters.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# +# finished_audio 内の MP3 にチャプターとメタデータを付ける。 +# +# chapters/add-chapters.sh # 最新の1件だけ (既定) +# chapters/add-chapters.sh --all # ファイル名に old を含むものを除く全件 +# +# 音声の置き場所は AUDIO_DIR で変えられる。既定はリポジトリと同じ階層の +# finished_audio (従来どおり show-notes と finished_audio が並んでいる前提)。 +# +# AUDIO_DIR=/path/to/mp3 chapters/add-chapters.sh +# +# episodes.yml は md/ep*.md から GitHub Actions が生成するので、 +# 先に最新の master を pull しておくこと。 + +set -euo pipefail + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +REPO_ROOT=$(cd "$SCRIPT_DIR/.." && pwd) +AUDIO_DIR=${AUDIO_DIR:-$(dirname "$REPO_ROOT")/finished_audio} + +if [ ! -d "$AUDIO_DIR" ]; then + echo "音声ディレクトリが見つかりません: $AUDIO_DIR" >&2 + echo "AUDIO_DIR=/path/to/mp3 で指定してください。" >&2 + exit 1 +fi + +# add-chapters.py は episodes.yml と cover_art.jpg を相対パスで開くので +# chapters/ に移動してから実行する。 +cd "$SCRIPT_DIR" + +mp3s=() +while IFS= read -r line; do + mp3s+=("$line") +done < <(ls -1t "$AUDIO_DIR"/*.mp3 2>/dev/null || true) + +if [ "${#mp3s[@]}" -eq 0 ]; then + echo "MP3 が見つかりません: $AUDIO_DIR" >&2 + exit 1 +fi + +targets=() +if [ "${1:-}" = "--all" ]; then + for mp3 in "${mp3s[@]}"; do + case "$(basename "$mp3")" in + *old*) echo "skip: $mp3" ;; + *) targets+=("$mp3") ;; + esac + done +elif [ $# -gt 0 ]; then + echo "不明な引数: $1" >&2 + echo "使い方: $0 [--all]" >&2 + exit 1 +else + targets=("${mp3s[0]}") +fi + +for mp3 in "${targets[@]}"; do + echo "add-chapters for $mp3" + python3 add-chapters.py "$mp3" +done diff --git a/chapters/requirements.txt b/chapters/requirements.txt index 6316a6a..62a8365 100644 --- a/chapters/requirements.txt +++ b/chapters/requirements.txt @@ -1,2 +1,4 @@ mutagen==1.44.0 -PyYAML==5.4 +# PyYAML 5.4 は Cython 3 系でビルドが通らず、新しめの Python では install できない +# (Python 3.11 で "Getting requirements to build wheel did not run successfully") +PyYAML>=6.0