最初に
以前、42Tokyoの課題をGitHubで管理する方法について考えた。
42Tokyoの課題をGitHubで管理する | tsito.me
GitHubを利用した課題の管理・Norminetteの自動化を考えた
この時点ではまだ入学前だったため、Moulinetteがどこまで提出物を見るのか、.github/以下のファイルが存在しても問題ないのか、かなり推測で書いていた。
その後42Tokyoに入学し、先日最初の課題であるlibftをクリアした。
実際に課題を提出してみてわかったことがいくつかあったので、前回記事の更新版として残しておく。
結論
少なくともlibftでは、GitHubで管理していたリポジトリをそのまま提出して問題なく通った。
具体的には、リポジトリ内に以下のような課題本体以外のファイルやディレクトリが存在していた。
.github/workflows/README.md.gitignore
これらが存在すること自体でMoulinetteに弾かれることはなかったし、なんならREADME.mdは課題の要件として必須となっていた。
ただし、これはあくまでlibftでの結果であり、すべての課題で同じとは限らない。課題ごとにsubjectの提出条件は違うので、「余分なファイルがあっても常に大丈夫」と一般化するつもりはない。
前回の仮説はだいたい合っていた
前回の記事では、Moulinetteの流れを以下のように予想していた。
①提出物をクローン
↓
②Norminette
↓
③コンパイル
↓
④テスト
↓
⑤結果集計
実際の内部実装はもちろん見えないが、libftを通した感触としては大きく外していなさそうだった。
少なくとも、指定された成果物であるlibft.aがmakeで生成でき、Norminetteに通り、関数の挙動が期待通りであれば、.github/や.gitignoreの存在だけで即アウトになるような挙動ではなかった。
前回いちばん気にしていた「GitHub Actions用のファイルを置いたまま提出してよいのか」という点については、libftでは問題なかったと言える。
ただしテンプレートは見直した
一方で、前回用意していた42-c-templateは入学後に見直した。
GitHub - bassaaaa/42-c-template: 42 subject template for C
42 subject template for C. Contribute to bassaaaa/42-c-template development by creating an account on GitHub.
最初のテンプレートでは、なんとなく一般的なCプロジェクトとしてsrc/やinc/を用意していた。
しかしlibftのsubjectでは、提出ファイルとしてMakefile, libft.h, ft_*.cが指定されており、要件として全ファイルをリポジトリのルートに配置する前提だった。
つまり、テンプレートが最初からsrc/やinc/を持っていると、むしろ課題要件からズレる可能性がある。
そこでテンプレートは以下の方針に更新した。
- 特定のディレクトリ構成を強制しない
src/やinc/をデフォルトで置かない- Makefileはあくまで雛形として、課題ごとの修正を前提にする
- READMEに「subjectを読んで必ず調整する」ことを明記する
テンプレートは便利だが、42の課題では「テンプレートに合わせる」のではなく「subjectに合わせる」べきである。
libftで実際に使った構成
libftでは、最終的に以下のような素直な構成にした。
.
├── Makefile
├── libft.h
├── ft_*.c
├── README.md
└── .github/
└── workflows/
├── format-c.yml
├── norminette.yml
└── notify-discord.yml
Makefileでは、ルート直下の.cを対象にしてlibft.aを作るようにした。
NAME := libft
NAME_A := $(NAME).a
SRCS := $(wildcard *.c)
INCDIR := .
OUTDIR := .out
OBJS := $(addprefix $(OUTDIR)/, $(SRCS:.c=.o))オブジェクトファイルは.out/以下に出すようにしている。
$(OUTDIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -I$(INCDIR) -c $< -o $@libft.aはルート直下に生成されるため、subjectの要件とも矛盾しない。
ただし、$(SRCS)にwildcardを使用していることで、レビュー中に物議を醸してしまった。
というのも、Norm規約のIII.11 Makefileには以下のように記載してある。
プロジェクトをコンパイルするために必要なすべてのソースファイルについて、 Makefile に名前を明示的に列挙するものとする。即ち、*.c、 *.o 等で記述してはならない。
つまり、Norm規約を遵守するのであれば$(SRCS) には.cのファイル名を一つずつ列挙する必要がある。
しかし今回結果的にwildcardでもMoulinetteを通っているため、機械採点的にはOKということになる。
この可否判断はレビュワー次第(Moulinetteに通ればOK派、Norm規約遵守派に分かれるかも…)と言うしかないため、めんどくさいかもしれないがファイル名を一つ一つ記載しておくのが吉かと思う。
GitHub Actionsは便利だった
前回作ったGitHub Actionsの方針は、そのまま役に立った。
特に便利だったのは以下の2つ。
- push時に
c_formatter_42を自動実行する - push時にNorminetteを実行してDiscordに通知する
ローカルでもNorminetteは実行するが、push後にもCIで確認されると安心感がある。
42の課題は、実装の正しさ以前にNormエラーで落ちる可能性がある。そこを機械的に潰せるだけでも、GitHub Actionsを入れる価値はあった。
ただし、c_formatter_42の自動コミットは便利な反面、意図しない差分が入る可能性もある。提出前には必ず最終差分を確認する運用にしている。
テスターはリポジトリに入れない
libftでは先輩方が作ってくれたテスターをかなり使った。
GitHub - usatie/libft-tester-tokyo: Tester for the libft project of 42 school
Tester for the libft project of 42 school. Contribute to usatie/libft-tester-tokyo development by creating an account on GitHub.
GitHub - Tripouille/libftTester: Tester for the libft project of 42 school
Tester for the libft project of 42 school. Contribute to Tripouille/libftTester development by creating an account on GitHub.
ただし、テスターは課題リポジトリに混ぜない方がよい。
手元でテスターをcloneして実行するのはよいが、提出対象のリポジトリにテストコードや外部ツールを含めると、subjectの「未使用ファイルを提出しない」という条件に触れる可能性がある。
自分の場合は、テスターはローカルで使うだけにして、提出用の管理対象には含めないようにした。
また、libft-tester-tokyoはMacOSでしか正常に動作しないため注意。
リモート運用自体はそのままでよかった
前回考えていた、GitHubをorigin、vogsphereを42_v1のような名前で追加する運用もそのまま使えた。
git remote add 42_v1 <vogsphereのURL>
git push 42_v1 mainリトライが必要になった場合は、42_v2, 42_v3のように増やしていけばよい。
GitHub側には普段の作業履歴を残し、提出時だけvogsphereにpushする。この分離はかなり扱いやすかった。
ただし、これはあくまでGitのremoteをどう分けるかの話であり、自分のPCからvogsphereへSSH接続できるかどうかは別問題だった。
自分の端末からvogsphereへSSH接続するには、校舎内Wi-Fiに接続している場合のみ可能なようだ。
例外的に、オンライン学生は校舎iMac以外からもアクセスできるようだが、このオンライン学生制度は古い仕組みで、「2023年4月28日以降の入学者には認められていない」と42TokyoのDiscordサーバに記載があった。さらに、この制度自体が2024年10月31日に廃止となったらしく、少なくとも通常の学生が「自分のPCからどこでもvogsphereへSSHできる」ということはなさそう。
そのため、提出時のpushは校舎iMac、または校舎内Wi-Fiに接続した自分の端末から行う前提で考えておくのがよいと思う。
今の運用方針
libftを通した後の自分の運用方針は以下。
- 課題ごとにGitHubリポジトリを作る
42-c-templateから始めるが、まずsubjectを読んで構成を決める- GitHub ActionsでフォーマットとNorminetteを回す
- テスターはローカルで使うが、提出対象には含めない
make,make clean,make fclean,make reを必ず確認する- 校舎端末または校内Wi-Fiに接続したPCからvogsphereへpushする
テンプレートで楽をする部分と、課題ごとに目視で確認する部分を分けるのが大事だと思う。
まとめ
入学前に考えていたGitHub管理の方針は、libftでは問題なく機能した。
特に、.github/以下のGitHub Actions設定を置いたままでもlibftのMoulinetteには通ったので、CIを使いながら課題を進める運用は現実的だとわかった。
一方で、最初の42-c-templateは少し一般的なCプロジェクトに寄せすぎていた。42の課題では、一般的な綺麗さよりもsubjectの指定に素直であることの方が重要だ。
そのため、テンプレートは「便利な初期セット」ではなく、「課題ごとに調整するための最低限の土台」として更新した。
次はget_next_lineまたはft_printfに進む。libftよりもファイル構成やbonusの扱いで迷う部分が増えそうなので、今回の運用をベースにしつつ、また必要があればテンプレートも更新していく。