{
  "$type": "site.standard.document",
  "content": [
    {
      "$type": "app.myblog.markdown",
      "lang": "ja",
      "markdown": "おはようございます。waturaです。TALES iOSアプリネタの記事です。\n\nこの記事は [note株式会社 Advent Calendar 2025](https://qiita.com/advent-calendar/2025/note) の 5日目の記事になります。\n\n## またあったねCocoaPods\n\nTALESには広告SDKが入っています。\n\n通常広告SDKはCocoaPodsで管理するのが一般的です。理由としては、メディエーションを提供しているGoogleのライブラリがCocoaPodsにしか対応していないためです。\n\n別れを告げたのに、またあったね!しかもほぼフルSwiftUIでモダンな実装を目指してつくったアプリでまたあうなんてね!!ということで、CocoaPodsの話です。\n\n## やっぱりCocoaPods界隈オワコンでは。。。\n\n今回、TALESアプリに組み込んだ一つのSDKの取得が、CI環境では不安定になり、CIがまともに動作しないという問題が発生しました。CIから使おうとすると、そのライブラリのCDNにアクセスできなくなるなんて,CIがない時代のライブラリなのでは?って思ってしまうようなCocoaPods界隈です。\n\n今回は、そのCDNにつながらない対策をGithub Releaseをつかって行ないました。\n\n基本的にはこれとかわらないような内容です。ただし、CocoaPodsです。というだけです。\n\n[**GitHub Private repo で XCFramework を配布する** _zenn.dev_](https://zenn.dev/d_date/articles/8b6ded8fdd2403#netrc%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)[](https://zenn.dev/d_date/articles/8b6ded8fdd2403#netrc%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)\n\n## 課題:CI環境でのSDK取得の不安定性\n\nTALES iOSでは、SomeAdSDKという外部の広告SDKをつかっています。このSDKは公式CDN(cdn.example.com)から配信されているのですが、Xcode Cloud環境で問題が発生していました\n\n*   DNS解決の失敗により、SDKのダウンロードが不安定\n    \n*   ビルド時にランダムに失敗し、開発フローが阻害される\n    \n*   ローカル環境では問題なく動作するため、原因の特定が困難\n    \n\nたぶん、Xcode Cloudからのアクセスがブロックされているんだろうなという理解です。  \nこの問題を解決するため、**GitHub ReleaseにSDKを保存し、CI環境からはGitHub経由で取得する**仕組みを構築しました。\n\n## 解決策:環境別のSDK取得元の切り替え\n\n前述のZenn記事にあるようにGithub Release経由で取得するというのが、楽そうであると考えました。  \nJWTの作成やGITHUB Tokenをローカルでも扱う必要があるのですが、瑣末なSDKであり、また、ローカルから取得では失敗していないので\n\n*   ローカル:公式CDN\n    \n*   CI: Github Release\n    \n\nと取得先を変更するようにしました。\n\n### 1\\. GitHub Releaseへの自動アップロード\n\nCIでつかえないので手元でしか動かせないという問題があるのですが,SDKの更新を自動化するスクリプトを作成しました。\n\n```\n#!/bin/bash\n\n# 最新バージョンを取得\nLATEST_VERSION=$(ruby -e \"require 'cocoapods'; spec = Pod::Specification.from_file('親.podspec'); puts spec.dependencies.find { |d| d.name == 'SomeAdSDK' }.requirement.to_s\")\n\n# GitHub Releaseの存在確認\nRELEASE_TAG=\"SomeAdSDK-v${VERSION}\"\nif gh release view \"$RELEASE_TAG\" &>/dev/null; then\n  echo \"Release already exists\"\n  exit 0\nfi\n\n# 公式CDNからダウンロード\ncurl -o \"${TMP_DIR}/${FILENAME}\" \"https://cdn.example.com/release-sdk/ios/${VERSION}/${FILENAME}\"\n\n# GitHub Releaseを作成してアップロード\ngh release create \"$RELEASE_TAG\" \\\n  \"${TMP_DIR}/${FILENAME}\" \\\n  --title \"SomeAdSDK ${VERSION}\" \\\n  --notes \"Mirrored from official CDN for CI stability\"\n\n# Github Release から asset urlを取得\nASSET_API_URL=$(gh release view \"$RELEASE_TAG\" --json assets --jq '.assets[0].apiUrl')\n```\n\n### 2\\. podspec\n\nCocoaPodsのライブラリはpodspecというファイルで定義されています。Package.swiftのようなファイルです。  \nアップデートスクリプトで取得した,ASSET\\_API\\_URLをつかってGithubから取得するようにします。  \nまた、GITHUB\\_TOKENはGithubアプリを作ってTOKEN取り出す別スクリプトとかでenvにいれるようにしています。\n\n```\nPod::Spec.new do |s|\n  s.name = 'SomeAdSDK'\n  s.version = '20250930'\n  \n  # CI環境ではGitHub Release Asset APIから取得\n  if ENV['CI'] && !ENV['CI'].to_s.empty? && ENV['GITHUB_TOKEN']\n    s.source = {\n      http: 'https://api.github.com/repos/org/repo/releases/assets/315017293',\n      type: 'zip',\n      headers: [\n        \"Authorization: Bearer #{ENV['GITHUB_TOKEN']}\",\n        'Accept: application/octet-stream'\n      ]\n    }\n  # ローカル環境では公式CDNから取得\n  else\n    s.source = {\n      http: 'https://cdn.example.com/release-sdk/ios/20250930/SomeAdSDK.framework-20250930.zip'\n    }\n  end\n  \n  s.vendored_frameworks = 'SomeAdSDK.framework'\nend\n```\n\n### 3\\. Podfileでのカスタムpodspecの参照\n\n```\n# カスタムpodspecを使用(GitHub Releaseから取得)\n# CI環境での公式CDNへのDNS解決問題を回避\npod 'SomeAdSDK', :podspec => 'SomeAdSDK.podspec'\n```\n\n## まとめ\n\nもうCocoaPodsは終わったんだよ?\n\n[**CocoaPods Trunk Read-only Plan - CocoaPods Blog** _The blog for CocoaPods.org the Cocoa Dependency ManagerThe De_ _blog.cocoapods.org_](https://blog.cocoapods.org/CocoaPods-Specs-Repo/)[](https://blog.cocoapods.org/CocoaPods-Specs-Repo/)\n\n* * *\n\nというところはともかくも、安定してCIが動くようになりました。  \nそもそも、他社は問題ないのか。もっとCocoaPodsの運用でイイ方法があるのかとかしりたいことはいろいろあります。が、動いているしもういいやという気分でもあります。\n\n今後やりたいこととしては、今はTALES iOSのリポジトリのReleaseにいれているんですが、別リポジトリさっさとつくってしまいたいですね。  \n広告SDKのためにタグとかreleaseきりまくるのもいやだよねぇとなるのや、カオスになっちゃうのでというところが理由ですね。\n\n* * *\n\n#noteアドカレ2025\n"
    }
  ],
  "path": "/blog/3mmcuyqkv5oet",
  "publishedAt": "2025-12-04T00:00:00Z",
  "site": "https://wtr.app",
  "tags": [
    "note"
  ],
  "textContent": "おはようございます。waturaです。TALES iOSアプリネタの記事です。\n\nこの記事は note株式会社 Advent Calendar 2025 の 5日目の記事になります。\n\nまたあったねCocoaPods\n\nTALESには広告SDKが入っています。\n\n通常広告SDKはCocoaPodsで管理するのが一般的です。理由としては、メディエーションを提供しているGoogleのライブラリがCocoaPodsにしか対応していないためです。\n\n別れを告げたのに、またあったね!しかもほぼフルSwiftUIでモダンな実装を目指してつくったアプリでまたあうなんてね!!ということで、CocoaPodsの話です。\n\nやっぱりCocoaPods界隈オワコンでは。。。\n\n今回、TALESアプリに組み込んだ一つのSDKの取得が、CI環境では不安定になり、CIがまともに動作しないという問題が発生しました。CIから使おうとすると、そのライブラリのCDNにアクセスできなくなるなんて,CIがない時代のライブラリなのでは?って思ってしまうようなCocoaPods界隈です。\n\n今回は、そのCDNにつながらない対策をGithub Releaseをつかって行ないました。\n\n基本的にはこれとかわらないような内容です。ただし、CocoaPodsです。というだけです。\n\nGitHub Private repo で XCFramework を配布する zenn.dev\n\n課題:CI環境でのSDK取得の不安定性\n\nTALES iOSでは、SomeAdSDKという外部の広告SDKをつかっています。このSDKは公式CDN(cdn.example.com)から配信されているのですが、Xcode Cloud環境で問題が発生していました\n\nDNS解決の失敗により、SDKのダウンロードが不安定\n\nビルド時にランダムに失敗し、開発フローが阻害される\n\nローカル環境では問題なく動作するため、原因の特定が困難\n\nたぶん、Xcode Cloudからのアクセスがブロックされているんだろうなという理解です。この問題を解決するため、GitHub ReleaseにSDKを保存し、CI環境からはGitHub経由で取得する仕組みを構築しました。\n\n解決策:環境別のSDK取得元の切り替え\n\n前述のZenn記事にあるようにGithub Release経由で取得するというのが、楽そうであると考えました。JWTの作成やGITHUB Tokenをローカルでも扱う必要があるのですが、瑣末なSDKであり、また、ローカルから取得では失敗していないので\n\nローカル:公式CDN\n\nCI: Github Release\n\nと取得先を変更するようにしました。\n\n1\\. GitHub Releaseへの自動アップロード\n\nCIでつかえないので手元でしか動かせないという問題があるのですが,SDKの更新を自動化するスクリプトを作成しました。\n\n#!/bin/bash\n\n# 最新バージョンを取得\nLATEST_VERSION=$(ruby -e \"require 'cocoapods'; spec = Pod::Specification.from_file('親.podspec'); puts spec.dependencies.find { |d| d.name == 'SomeAdSDK' }.requirement.to_s\")\n\n# GitHub Releaseの存在確認\nRELEASE_TAG=\"SomeAdSDK-v${VERSION}\"\nif gh release view \"$RELEASE_TAG\" &>/dev/null; then\n  echo \"Release already exists\"\n  exit 0\nfi\n\n# 公式CDNからダウンロード\ncurl -o \"${TMP_DIR}/${FILENAME}\" \"https://cdn.example.com/release-sdk/ios/${VERSION}/${FILENAME}\"\n\n# GitHub Releaseを作成してアップロード\ngh release create \"$RELEASE_TAG\" \\\n  \"${TMP_DIR}/${FILENAME}\" \\\n  --title \"SomeAdSDK ${VERSION}\" \\\n  --notes \"Mirrored from official CDN for CI stability\"\n\n# Github Release から asset urlを取得\nASSET_API_URL=$(gh release view \"$RELEASE_TAG\" --json assets --jq '.assets[0].apiUrl')\n\n2\\. podspec\n\nCocoaPodsのライブラリはpodspecというファイルで定義されています。Package.swiftのようなファイルです。アップデートスクリプトで取得した,ASSET\\_API\\_URLをつかってGithubから取得するようにします。また、GITHUB\\_TOKENはGithubアプリを作ってTOKEN取り出す別スクリプトとかでenvにいれるようにしています。\n\nPod::Spec.new do |s|\n  s.name = 'SomeAdSDK'\n  s.version = '20250930'\n  \n  # CI環境ではGitHub Release Asset APIから取得\n  if ENV['CI'] && !ENV['CI'].to_s.empty? && ENV['GITHUB_TOKEN']\n    s.source = {\n      http: 'https://api.github.com/repos/org/repo/releases/assets/315017293',\n      type: 'zip',\n      headers: [\n        \"Authorization: Bearer #{ENV['GITHUB_TOKEN']}\",\n        'Accept: application/octet-stream'\n      ]\n    }\n  # ローカル環境では公式CDNから取得\n  else\n    s.source = {\n      http: 'https://cdn.example.com/release-sdk/ios/20250930/SomeAdSDK.framework-20250930.zip'\n    }\n  end\n  \n  s.vendored_frameworks = 'SomeAdSDK.framework'\nend\n\n3\\. Podfileでのカスタムpodspecの参照\n\n# カスタムpodspecを使用(GitHub Releaseから取得)\n# CI環境での公式CDNへのDNS解決問題を回避\npod 'SomeAdSDK', :podspec => 'SomeAdSDK.podspec'\n\nまとめ\n\nもうCocoaPodsは終わったんだよ?\n\nCocoaPods Trunk Read-only Plan - CocoaPods Blog The blog for CocoaPods.org the Cocoa Dependency ManagerThe De blog.cocoapods.org\n\nというところはともかくも、安定してCIが動くようになりました。そもそも、他社は問題ないのか。もっとCocoaPodsの運用でイイ方法があるのかとかしりたいことはいろいろあります。が、動いているしもういいやという気分でもあります。\n\n今後やりたいこととしては、今はTALES iOSのリポジトリのReleaseにいれているんですが、別リポジトリさっさとつくってしまいたいですね。広告SDKのためにタグとかreleaseきりまくるのもいやだよねぇとなるのや、カオスになっちゃうのでというところが理由ですね。\n\n#noteアドカレ2025",
  "title": "CocoaPods のライブラリをGithub Releaseから取得するようにしてみた",
  "updatedAt": "2026-05-20T21:47:19Z"
}