From 0e938b3f5585b4daefee183632baedaddec873f2 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 08:35:53 +0000 Subject: [PATCH 1/5] =?UTF-8?q?ci:=20Crystal=20=E3=82=92=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=E3=81=97=20ameba=20=E3=82=92=20Crystal=201.21=20=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C=E3=82=B3=E3=83=9F=E3=83=83=E3=83=88=E3=81=AB=E8=BF=BD?= =?UTF-8?q?=E5=BE=93=E3=81=95=E3=81=9B=E3=82=8B=EF=BC=88#108=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crystal: latest が 1.21.0 に上がったことで、shards install の ameba postinstall がコンパイルできず CI が常に落ちる状態になっていた。 (undefined method 'next_string_array_token' for Crystal::Lexer) - ci.yml の Crystal を 1.21.0 に固定し、Crystal 側の更新で不意に壊れないようにする - ameba を Crystal 1.21 対応が入った master のコミットに固定する 安定版(1.7 系)がリリースされたら version 指定に戻す Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01MoGxJDiZa8c2E3PVAnxbK8 --- .github/workflows/ci.yml | 4 +++- shard.lock | 2 +- shard.yml | 7 ++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 074d23c..a5e1358 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,12 @@ jobs: - name: checkout uses: actions/checkout@v4 + # crystal: latest だと Crystal の更新でいきなり CI が壊れるため固定する。 + # 上げるときは ameba 側の対応状況も合わせて確認すること(issue #108)。 - name: install crystal uses: crystal-lang/install-crystal@v1 with: - crystal: latest + crystal: 1.21.0 - name: install shards run: shards install diff --git a/shard.lock b/shard.lock index f612c4d..0970e98 100644 --- a/shard.lock +++ b/shard.lock @@ -2,5 +2,5 @@ version: 2.0 shards: ameba: git: https://github.com/crystal-ameba/ameba.git - version: 1.6.4 + version: 1.7.0-dev+git.commit.cdd58b34b0d8a9c785d67183a7a8f07541549e55 diff --git a/shard.yml b/shard.yml index dec4eb0..d7afc72 100644 --- a/shard.yml +++ b/shard.yml @@ -13,6 +13,11 @@ crystal: ">= 1.20.0" development_dependencies: ameba: github: crystal-ameba/ameba - version: ~> 1.6 + # Crystal 1.21 で Crystal::Lexer#next_string_array_token が削除され、 + # `~> 1.6` で解決される最新の安定版 1.6.4 はコンパイルできない。対応は + # master に入っているが安定版のリリースがまだ無いため、修正を含むコミットに + # 固定して追従する。1.7 系がリリースされたら version 指定に戻すこと + # (issue #108)。 + commit: cdd58b34b0d8a9c785d67183a7a8f07541549e55 license: MIT From a8c21337a367524bbc9614cba51d6d89011c18a5 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 08:38:08 +0000 Subject: [PATCH 2/5] =?UTF-8?q?ci:=20ameba=20=E3=81=AE=E3=83=90=E3=82=A4?= =?UTF-8?q?=E3=83=8A=E3=83=AA=E3=82=92=E6=98=8E=E7=A4=BA=E7=9A=84=E3=81=AB?= =?UTF-8?q?=E3=83=93=E3=83=AB=E3=83=89=E3=81=99=E3=82=8B=EF=BC=88#108?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 追従先の ameba(1.7 系)は shard.yml から postinstall が外れており、 shards install だけでは bin/ameba が作られず ./bin/ameba が 127 で落ちる。 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01MoGxJDiZa8c2E3PVAnxbK8 --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5e1358..c072cc6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,12 @@ jobs: - name: check format run: crystal tool format --check + # 追従先の ameba(1.7 系)は shard.yml から postinstall が外れており、 + # shards install だけでは bin/ameba が作られないため明示的にビルドする + # (issue #108)。 + - name: build ameba + run: crystal build lib/ameba/src/cli.cr -o bin/ameba + - name: lint with ameba run: ./bin/ameba From 51c031228710e60dbe02ed423a31d8a4db47860e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 08:40:07 +0000 Subject: [PATCH 3/5] =?UTF-8?q?ci:=20ameba=20=E3=81=AE=E3=83=93=E3=83=AB?= =?UTF-8?q?=E3=83=89=E5=85=88=E3=83=87=E3=82=A3=E3=83=AC=E3=82=AF=E3=83=88?= =?UTF-8?q?=E3=83=AA=E3=82=92=E4=BD=9C=E6=88=90=E3=81=99=E3=82=8B=EF=BC=88?= =?UTF-8?q?#108=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bin/ が存在せずリンクに失敗していた。 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01MoGxJDiZa8c2E3PVAnxbK8 --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c072cc6..280e751 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,9 @@ jobs: # shards install だけでは bin/ameba が作られないため明示的にビルドする # (issue #108)。 - name: build ameba - run: crystal build lib/ameba/src/cli.cr -o bin/ameba + run: | + mkdir -p bin + crystal build lib/ameba/src/cli.cr -o bin/ameba - name: lint with ameba run: ./bin/ameba From c580bf82fcd1e4fe2c4889abc84ec3565d10bd4c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 08:43:19 +0000 Subject: [PATCH 4/5] =?UTF-8?q?style:=20ameba=201.7=20=E7=B3=BB=E3=81=A7?= =?UTF-8?q?=E6=96=B0=E3=81=9F=E3=81=AB=E6=A4=9C=E5=87=BA=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=81=9F=E6=8C=87=E6=91=98=E3=82=92=E4=BF=AE=E6=AD=A3=E3=81=99?= =?UTF-8?q?=E3=82=8B=EF=BC=88#108=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 追従先の ameba は Style/RedundantNilInControlExpression の追加と Style/RedundantBegin / Style/HeredocIndent の検出範囲拡大により、 既存コード 8 箇所を指摘する。いずれも Correctable な機械的修正。 - 戻り値が nilable なメソッドの `return nil` を `return` に - ブロック直下の begin/rescue をブロックの rescue に - ヒアドキュメント本文を 2 スペースインデントに(文字列の内容は不変) Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01MoGxJDiZa8c2E3PVAnxbK8 --- spec/github/models_spec.cr | 46 +++++++++++++++++++------------------- src/discord/models.cr | 8 +++---- src/github/models.cr | 2 +- src/github/usecase.cr | 2 +- src/main.cr | 10 ++++----- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/spec/github/models_spec.cr b/spec/github/models_spec.cr index 6f2449e..c11c451 100644 --- a/spec/github/models_spec.cr +++ b/spec/github/models_spec.cr @@ -174,26 +174,26 @@ private def notification_with(url = "", repo_html_url : String? = nil) end NOTIFICATIONS_FIXTURE = <<-JSON -[ - { - "reason": "mention", - "subject": { - "title": "Spurious failure", - "url": "https://api.github.com/repos/octocat/Hello-World/issues/1", - "latest_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments/1", - "type": "Issue" - }, - "updated_at": "2026-07-14T00:00:00Z", - "repository": { - "full_name": "octocat/Hello-World", - "html_url": "https://github.com/octocat/Hello-World", - "owner": { - "login": "octocat", - "avatar_url": "https://github.com/images/error/octocat.gif", - "html_url": "https://github.com/octocat" - } - }, - "subscription_url": "https://api.github.com/notifications/threads/1/subscription" - } -] -JSON + [ + { + "reason": "mention", + "subject": { + "title": "Spurious failure", + "url": "https://api.github.com/repos/octocat/Hello-World/issues/1", + "latest_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments/1", + "type": "Issue" + }, + "updated_at": "2026-07-14T00:00:00Z", + "repository": { + "full_name": "octocat/Hello-World", + "html_url": "https://github.com/octocat/Hello-World", + "owner": { + "login": "octocat", + "avatar_url": "https://github.com/images/error/octocat.gif", + "html_url": "https://github.com/octocat" + } + }, + "subscription_url": "https://api.github.com/notifications/threads/1/subscription" + } + ] + JSON diff --git a/src/discord/models.cr b/src/discord/models.cr index 84db6a4..60be7c3 100644 --- a/src/discord/models.cr +++ b/src/discord/models.cr @@ -71,7 +71,7 @@ module Discord lines = [] of String lines << EVERYONE_MENTION if mention lines.concat pretexts.uniq - return nil if lines.empty? + return if lines.empty? Discord.truncate(lines.join("\n"), CONTENT_LIMIT) end end @@ -122,7 +122,7 @@ module Discord # Slack で使う "#RRGGBB" 形式の色を Discord が要求する Int32 へ変換する。 def self.color_from_hex(hex : String?) : Int32? - return nil unless hex + return unless hex hex.lchop('#').to_i?(16) end end @@ -139,7 +139,7 @@ module Discord def self.from_message(message : Notify::Message) : Author? # Discord は author に name 必須のため、名前が無ければ author 自体を付けない。 - return nil unless message.author_name + return unless message.author_name # 空文字の URL は Discord に 400 で弾かれるため nil にする。 Author.new(message.author_name, message.author_link.presence, message.author_icon.presence) end @@ -156,7 +156,7 @@ module Discord def self.from_message(message : Notify::Message) : Footer? # Discord は footer に text 必須のため、footer が無ければ付けない。 - return nil unless message.footer + return unless message.footer # 空文字の icon_url は Discord に 400 で弾かれるため nil にする # (アラートは footer_icon: "" で来るため特に重要)。 Footer.new(message.footer, message.footer_icon.presence) diff --git a/src/github/models.cr b/src/github/models.cr index 15fc9ab..7ad6cd0 100644 --- a/src/github/models.cr +++ b/src/github/models.cr @@ -143,7 +143,7 @@ module Github # 限り、末尾セグメントが数値なら返す。Commit(末尾が SHA)や末尾スラッシュ、 # URL が無い場合などは nil を返す(issue #96)。 def number : String? - return nil unless type.in?(NUMBERED_TYPES) + return unless type.in?(NUMBERED_TYPES) segment = url.chomp('/').split('/').last? segment if segment && segment.matches?(/\A\d+\z/) end diff --git a/src/github/usecase.cr b/src/github/usecase.cr index b2574a7..28f2094 100644 --- a/src/github/usecase.cr +++ b/src/github/usecase.cr @@ -29,7 +29,7 @@ module Github end private def truncate_body(body : String?) : String? - return nil unless text = body.try(&.presence) + return unless text = body.try(&.presence) text.size > BODY_LIMIT ? "#{text[0, BODY_LIMIT]}…" : text end end diff --git a/src/main.cr b/src/main.cr index 385016e..dc95b4e 100644 --- a/src/main.cr +++ b/src/main.cr @@ -45,10 +45,8 @@ error_uc = Error::Usecase.new( ) Serverless::Lambda.handler "github_notifications_slack" do |_| - begin - notify_uc.check_notifications - rescue error - error_uc.alert error - raise error - end + notify_uc.check_notifications +rescue error + error_uc.alert error + raise error end From 09cd75e4b48d1e3eb68666b3bd75770c4f655f6b Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 9 Aug 2026 15:21:37 +0000 Subject: [PATCH 5/5] =?UTF-8?q?ci:=20=E3=83=87=E3=83=97=E3=83=AD=E3=82=A4?= =?UTF-8?q?=E7=94=A8=E3=81=AE=E3=83=93=E3=83=AB=E3=83=89=E3=82=A4=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=82=82=20Crystal=20=E3=81=AE=E3=83=90?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E3=81=A7=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=E3=81=99=E3=82=8B=EF=BC=88#108=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit serverless.yml のビルドは crystallang/crystal:latest-alpine を使っており、 CI だけ 1.21.0 に固定しても本番成果物は latest でコンパイルされていた。 Crystal が更新されると検証済みと違うコンパイラで成果物が作られ、互換性が 壊れていれば deploy も突然落ちる。ci.yml と同じ 1.21.0 に固定する。 PR #109 のレビュー指摘対応。 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01MoGxJDiZa8c2E3PVAnxbK8 --- .github/workflows/ci.yml | 3 ++- serverless.yml | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 280e751..bf97f2d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,8 @@ jobs: uses: actions/checkout@v4 # crystal: latest だと Crystal の更新でいきなり CI が壊れるため固定する。 - # 上げるときは ameba 側の対応状況も合わせて確認すること(issue #108)。 + # 上げるときは ameba 側の対応状況と、serverless.yml のビルドイメージの + # タグも合わせて確認すること(issue #108)。 - name: install crystal uses: crystal-lang/install-crystal@v1 with: diff --git a/serverless.yml b/serverless.yml index 4757899..331073e 100644 --- a/serverless.yml +++ b/serverless.yml @@ -24,8 +24,13 @@ custom: # # chmod はコンテナ内(root)で実行する。Linux ランナーでは生成物が # root 所有になり、コンテナ外の runner ユーザーでは chmod できないため。 + # + # イメージのタグは latest ではなくバージョンで固定する。latest のままだと + # Crystal の更新で、CI(ci.yml)が検証したのと違うコンパイラで本番成果物が + # 作られてしまい、互換性が壊れた場合は deploy も突然失敗する。 + # ci.yml の crystal バージョンと揃えて上げること(issue #108)。 'before:package:createDeploymentArtifacts': | - docker run --rm --platform linux/arm64 -v "$PWD":/work -w /work crystallang/crystal:latest-alpine \ + docker run --rm --platform linux/arm64 -v "$PWD":/work -w /work crystallang/crystal:1.21.0-alpine \ sh -c "apk add --no-cache openssl-libs-static zlib-static libevent-static && crystal build --link-flags -static -o bootstrap src/main.cr && chmod +x bootstrap" provider: