【個人開発】Githubのプロフィールに、Qiita・Zennの記事などを一覧表示させる、Github Actionsのアクション作ったよ！

# 宣伝

GithubのプロフィールはREADMEによって管理できることはご存知かと思います。
[プロフィールの README を管理する - GitHub Docs](https://docs.github.com/ja/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme)

そのREADMEにて、Qiita・Zennで書いた記事や、connpassの参加イベントを取得することで、最新のアクティビティを表示したいという要望を叶えるのが本アクションです。
以下のようなプロフィールを作ることが出来ます。

![Screen Shot 2022-02-16 at 11.21.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496036/91c6cfa5-ef26-0c5a-a8f8-e9fdab6ef354.png)

使い方は、プロフィールのリポジトリにymlファイルを一個追加し、READMEに書き換え用記述を置くだけです。
アクション使用者はIDなどを設定するだけで良いという、なるべく簡単なインターフェースにすることを心がけました。
Github Actionsには定期実行の仕組みがあり、1日1回自動で更新させるといったことも可能です。
筆者のプロフィールでは以下のymlファイルとREADMEを置いてます。

```yaml:.github/workflows/main.yml
name: profile updater

on:
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch:

jobs:
  profile-updater:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: kumackey/profile-updater@v1
        with:
          zenn_user_id: kumackey
          connpass_nickname: kumackey
          qiita_user_id: kumackey
      - name: Commit and push
        run: |
          git config --local user.name "GitHub Actions"
          git config --local user.email "action@github.com"
          git add .
          git commit -m "profile updated" || true
          git push origin main
```

```text:README.md
(略)

# Zenn Articles

<!-- profile updater begin: zenn -->
(略)
<!-- profile updater end: zenn -->

# Qiita Articles

<!-- profile updater begin: qiita -->
(略)
<!-- profile updater end: qiita -->

# connpass Events

<!-- profile updater begin: connpass -->
(略)
<!-- profile updater end: connpass -->

```

参考(筆者のプロフィールリポジトリ): https://github.com/kumackey/kumackey

詳細は以下リポジトリを見てください。
[kumackey/profile-updater](https://github.com/kumackey/profile-updater)

# 開発

## 着想

先駆者が割と多くいて、自分も作ってみたいと思い開発しました。
リポジトリを見に行ったりして、大いに参考にさせてもらいました。

[mikkame on Twitter: "GitHub ActionsでQiita/Zennの投稿をGitHubプロフィールに自動反映できるようにした](https://twitter.com/mikkameee/status/1360887240587571201)
[シェルスクリプトでZennの投稿をGitHubプロフィールに自動反映してみる](https://zenn.dev/captain_blue/articles/update-github-profile-automatically)
[【GitHub Actions】GitHubのプロフィールを自動更新する仕組みを作った - yyh-gl's Tech Blog](https://yyh-gl.github.io/tech-blog/blog/profile-readme-updater/)
[githubActionsを定期実行させて、オリジナルなREADME.mdをつくる](https://zenn.dev/kata_n/articles/5fed5e6e8f1cd7)
[Actions Readme Feed · Actions · GitHub Marketplace](https://github.com/marketplace/actions/actions-readme-feed)

## 使用技術

GoとGithub Actionsだけです。
業務ではGoを書いたことはありますが、個人開発では初めてまともに使いました。
感想になっちゃいますが、Dockerに乗せるのがクソ楽だったり、ライブラリを気軽に使えたり、構造体リッチにできたのは満足度が高いポイントでした。
何より書いてて安心感があり、本記事作成までにv1.0〜v1.4まで出しましたが、最初期の開発はともかくとして、改修は非常に楽でした。

## 設計

```text
.
├── Dockerfile
├── action.yml
├── cmd
│   └── main.go
└── pkg
    ├── adapter
    │   └── ...
    ├── domain
    │   └──  ...
    └── usecase
        └── ...

```

設計は一応はClean Architectureの思想でやりました。
依存はadapter -> usecase -> domainという方向にし、外部API通信やIOは詳細であるとしてadapterに詰め込みました。
ControllerやPresenterに該当する層は~~面倒だったので~~作ってないため、近いのはヘキサゴナルアーキテクチャだと思います。

[ドメイン駆動設計で実装を始めるのに一番とっつきやすいアーキテクチャは何か[DDD] - little hands' lab](https://little-hands.hatenablog.com/entry/2017/10/04/231743)

## コア技術

特にコアとなった技術や、参考になった記事などを紹介します。
こういうやり方もあるよ、みたいなのあれば是非教えてください！

### Github Actionsのアクション

アクションを利用することはあっても、アクションを作ったことはなかったです。
公式ドキュメントが非常に充実していて、ハンズオンで概要を学べてオススメです。

[アクションの作成 - GitHub Docs](https://docs.github.com/ja/actions/creating-actions)

### 正規表現

READMEへの置換は正規表現で実現しました。
Goの正規表現は遅い遅いって言われていたものの、他手段では代替が出来なさそうでした。

[regexp package - regexp - pkg.go.dev](https://pkg.go.dev/regexp)
[なぜGo言語の正規表現は遅いと言われるの？ - Qiita](https://qiita.com/momotaro98/items/09d0f968d44c7027450d)

改行コードは正規表現ではうまく扱えないっぽかったので、一度改行コードを別文字で置換してから戻すというやり方を採用しました。
なので改行コードがLFに強制されてしまうという問題を抱えてます。

[Go 言語で改行コードを変換する（正規表現以外の解） - Qiita](https://qiita.com/spiegel-im-spiegel/items/f1cc014ecb233afaa8af)

### RSS

QiitaとZennはRSSを使って取得してます。
本当はいいね数などを表示したかったですが、以下理由で断念です。

・ZennはAPIがない。クローリングは流石に~~面倒~~やりすぎ。
・QiitaはAPIはあるもののAPI認証キーが必要だったため、アクション上でステートレスに実行するのは~~非常に面倒~~難しいという判断になった。

[ZennをRSSフィードで購読する](https://zenn.dev/zenn/articles/zenn-feed-rss)
[記事をrssリーダーで読む - Qiita](https://qiita.com/tukiyo3/items/5b1051e63c7a32bfa48b)

GoでXMLをデコードする方法に関しては以下が参考になりました。
~~というかそのままパクりました。~~

[Goのencoding/xmlの使い方について雑に紹介](https://zenn.dev/nnabeyang/scraps/a1429f7f1214e9)

### connpass API

認証不要のAPIだったので飛びつきました。

[APIリファレンス - connpass](https://connpass.com/about/api/)

で、~~面倒だったので~~コードを高品質にするためにも以下ライブラリを使わせていただきました。

[tenntenn/connpass: An API client of connpass](https://github.com/tenntenn/connpass)