メインコンテンツにジャンプ
CI/CD

Capacitorで自動化されたGitHubアクションを使用したIOSのビルド

5分以内にfastlaneとGitHubアクションを使用したIOS IonicアプリのCI/CDパイプラインの設定方法(2022)

マーティン・ドナディュー

マーティン・ドナディュー

コンテンツマーケター

Capacitorで自動化されたGitHubアクションを使用したIOSのビルド

iOSの自動ビルドにGitHubアクションを使用する

CI/CDの設定をCapacitorアプリケーションに適用することは複雑で時間がかかることがあります。ここでは、必要な情報を簡単にまとめました。

現在、__CAPGO_KEEP_0__ビルドを使用することをお勧めしています。 CapgoビルドとCapgoCLIを使用する ネイティブCapacitorビルドのために使用します。 このFastlane Matchガイドは、既存のGitHubアクションパイプラインを維持するチーム向けに残されていますが、新しいiOSビルドの場合はCapgoCLIを使用するようにしてください。そうすることで、Fastlane、Matchリポジトリ、Xcodeランナー、証明書、アップロードスクリプトの維持を自分で行う必要がなくなります。

CapgoビルドはCapgoによってCI/CDを実行します。

Fastlane Match、Xcodeランナー、証明書、プロビジョニングプロファイル、アップロードスクリプトの維持をスキップします。 Capgoビルド 既存のCI/CDパイプラインから署名されたネイティブiOSビルドを実行します。

  • 既存のパイプラインと互換性があります。: Capgo を GitHub からビルドするトリガー npx cap sync.
  • : CI シークレットから署名: App Store Connect のキーや証明書、プロビジョニングプロファイル、パスワード、チーム ID を CI シークレットに保存
  • : __CAPGO_KEEP_0__ ビルドは Apple のビルド環境を維持しているので、macOS ランナー、Xcode イメージ、Fastlane、または Match リポジトリを管理する必要はありません: Capgo Build provides maintained Apple build environments, so you do not have to manage macOS runners, Xcode images, Fastlane, or Match repositories.
  • : QA で署名されたアーティファクトをダウンロードしたり、__CAPGO_KEEP_0__ __CAPGO_KEEP_1__ を通じてリリースビルドを提出したりできます: Download signed artifacts for QA or submit release builds through the Capgo CLI.

: __CAPGO_KEEP_0__ プランは $12/月から始まります

  • Capgo plans start at $12/month
  • : 追加のビルド分数はクレジットを通じて 1 分あたり請求されます
  • : __CAPGO_KEEP_0__ ビルドを CI/CD に設定する

Set up Capgo Build in CI/CD

マニュアルセットアップガイド

ここで、行う必要のあることを説明します:

iOS向けのFastlaneとGitHubアクションを使用した継続的デリバリ

前提条件

チュートリアルを続ける前に…

価格に関する重要な注意事項

価格 GitHub アクション

https://github.com/features/actions

サービスは、選択したマシンに応じて、制限まで無料です。
このチュートリアルで使用するのは macOS マシンです。スクリーンショットに表示されている価格と制限(価格はこのチュートリアルの作成時点のもので、将来の変更が可能です)をご覧になれます。

🔴 要件と価格について注意した後、続ける場合はどうですか?

📣 この投稿では、iTunes Connectでアプリを作成し、Apple エコシステムの証明書を取得していることを前提としています。Fastlaneによってすべてがコピーされます。

では、始めましょう!

この投稿で従う手順

  1. App Store Connectを使用してFastlane MatchをAPI
  2. 要件
  3. App Store Connect API キーを作成する
  4. App Store Connect API キーを使用する
  5. Fastlaneファイルをコピーする
  6. Fastlane matchを設定する

1. App Store Connectを使用してFastlane MatchをAPI

2021年2月以降、すべてのユーザーはApp Store Connectにサインインするために2要素認証または2段階認証が必要になります。この追加のセキュリティ層は、Apple IDのセキュリティを確保するために役立ちます。
From Apple Support

matchを始めるには、既存の証明書を取り消す必要がありますが、心配はいりません。新しい証明書は直接取得できます。

要件

App Store Connect API を使用できるようにするには、Fastlane は 3 つの ものが必要です。

  1. 発行者 ID。
  2. キー ID。
  3. キー ファイルまたはキー コンテンツ。

App Store Connect API キーを作成する

キーを生成するには、App Store Connect での管理者権限が必要です。管理者権限がない場合は、この記事を指示することで、関連する人に権限を与えることができます。次に、以下の手順に従ってください。

1 — App Store Connect にログインする 2 — Users and Access を選択する.

3 — "Keys" を選択する 4 — "+" をクリックしてキーを作成する.

App Store Connect ユーザー アクセス

3 — インテグレーション タブを選択します。

App Store Connect API インテグレーション

4 — Generate API キーまたは Add (+) ボタンをクリックします。

App Store Connect API キーを作成します

5 — キーの名前を入力してください。名前はあなたの参照用であり、キーの部分ではありません。

App Store Connect API キーを作成する名前

6 — アクセス下で、キーのロールを選択してください。キーのロールは、チームのユーザーに適用されるロールと同じです。詳細は ロールの権限を参照してください。 We recommend to select.

App manager

APIのキーは、特定のアプリにアクセスすることができない。

新しいキー名、キーID、ダウンロードリンク、他情報がページに表示される。

App Store Connectダウンロードキー

必要な3つの情報をすべてここから取得することができる。
<1> Issue ID.
<2> Key ID.
&#x3C;3> Click “Download API Key” to download your API private key. The download link appears only if the private key has not yet been downloaded. Apple does not keep a copy of the private key. So, you can download it only once.

🔴 プライベートキーを安全な場所に保存してください。キーを共有しないようにしてください。キーをcode リポジトリに保存しないようにしてください。クライアントサイドのcode にキーを含めないようにしてください。

App Store Connect API キーを使用する

API キー ファイル(ダウンロードしたp8ファイル)、キーID、発行者IDが必要です。これらの情報をFastlaneにinputする方法は複数あります。Fastlaneの新しいアクションを使用して、 app_store_connect_api_keyFastlaneドキュメントを参照してください。 Fastlaneドキュメントを参照してください。. CI環境の多くで環境変数を設定できるため、最も簡単な方法だと思います。

App Store ConnectのAPIキーを使用してFastlaneを管理できるようになりました!

2. Fastlaneファイルをコピーする

Fastlaneは、Android Studioを使用せずにモバイル開発タスクを自動化するためのRubyライブラリです。Fastlaneを使用すると、カスタムの「レーン」を構成できます。これらの「レーン」には、通常のAndroid Studioを使用して実行するタスクを実行する「アクション」が含まれます。Fastlaneを使用すると、多くのことが実行できますが、このチュートリアルの目的では、コアアクションの少数を使用します。

プロジェクトのルートディレクトリにFastlaneフォルダを作成し、次のファイルをコピーしてください: Fastfile

default_platform(:ios)

DEVELOPER_APP_IDENTIFIER = ENV["DEVELOPER_APP_IDENTIFIER"]
DEVELOPER_APP_ID = ENV["DEVELOPER_APP_ID"]
PROVISIONING_PROFILE_SPECIFIER = ENV["PROVISIONING_PROFILE_SPECIFIER"]
TEMP_KEYCHAIN_USER = ENV["TEMP_KEYCHAIN_USER"]
TEMP_KEYCHAIN_PASSWORD = ENV["TEMP_KEYCHAIN_PASSWORD"]
APPLE_ISSUER_ID = ENV["APPLE_ISSUER_ID"]
APPLE_KEY_ID = ENV["APPLE_KEY_ID"]
APPLE_KEY_CONTENT = ENV["APPLE_KEY_CONTENT"]
GIT_USERNAME = ENV["GIT_USERNAME"]
GIT_TOKEN = ENV["GIT_TOKEN"]

def delete_temp_keychain(name)
  delete_keychain(
    name: name
  ) if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
end

def create_temp_keychain(name, password)
  create_keychain(
    name: name,
    password: password,
    unlock: false,
    timeout: 0
  )
end

def ensure_temp_keychain(name, password)
  delete_temp_keychain(name)
  create_temp_keychain(name, password)
end

platform :ios do
  lane :build do
    build_app(
      configuration: "Release",
      workspace: "./ios/App/App.xcworkspace",
      scheme: "App",
      export_method: "app-store",
      export_options: {
        provisioningProfiles: { 
            DEVELOPER_APP_ID => "#{PROVISIONING_PROFILE_SPECIFIER}"
        }
      }
    )
  end
  lane :refresh_profiles do
    match(
      type: "development",
      force: true)
    match(
      type: "adhoc",
      force: true)
  end
  desc "Register new device"
  lane :register_new_device do  |options|
      device_name = prompt(text: "Enter the device name: ")
      device_udid = prompt(text: "Enter the device UDID: ")
      device_hash = {}
      device_hash[device_name] = device_udid
      register_devices(
                       devices: device_hash
                       )
    refresh_profiles
  end
  lane :closed_beta do
    keychain_name = TEMP_KEYCHAIN_USER
    keychain_password = TEMP_KEYCHAIN_PASSWORD
    ensure_temp_keychain(keychain_name, keychain_password)

    api_key = app_store_connect_api_key(
      key_id: APPLE_KEY_ID,
      issuer_id: APPLE_ISSUER_ID,
      key_content: APPLE_KEY_CONTENT,            
      duration: 1200,            
      in_house: false
    )

    match(
      type: 'appstore',
      git_basic_authorization: Base64.strict_encode64("#{GIT_USERNAME}:#{GIT_TOKEN}"),
      readonly: true,
      keychain_name: keychain_name,
      keychain_password: keychain_password,
      api_key: api_key
    )

    gym(
      configuration: "Release",
      workspace: "./ios/App/App.xcworkspace",
      scheme: "App",
      export_method: "app-store",
      export_options: {
        provisioningProfiles: { 
            DEVELOPER_APP_ID => "#{PROVISIONING_PROFILE_SPECIFIER}"
        }
      }
    )

    pilot(
      apple_id: "#{DEVELOPER_APP_ID}",
      app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
      skip_waiting_for_build_processing: true,
      skip_submission: true,
      distribute_external: false,
      notify_external_testers: false,
      ipa: "./App.ipa"
    )

    delete_temp_keychain(keychain_name)
  end
  lane :submit_review do
    version = ''
    Dir.chdir("..") do
      file = File.read("package.json")
      data = JSON.parse(file)
      version = data["version"]
    end
    deliver(
      app_version: version,
      submit_for_review: true,
      automatic_release: true,
      force: true, # Skip HTMl report verification
      skip_metadata: false,
      skip_screenshots: false,
      skip_binary_upload: true
    )
  end
end

Appfile

app_identifier(ENV["DEVELOPER_APP_IDENTIFIER"])
apple_id(ENV["FASTLANE_APPLE_ID"])
itc_team_id(ENV["APP_STORE_CONNECT_TEAM_ID"])
team_id(ENV["DEVELOPER_PORTAL_TEAM_ID"])

Fastlaneを設定する

Fastlaneのmatch matchはiOSの__CAPGO_KEEP_0__署名の新しいアプローチです。Fastlaneのmatchは、iOSアプリの必要な証明書とプロビジョニングプロファイルを管理するチームに簡単にアクセスできるようにします。 is a new approach to iOS’s code signing. Fastlane match makes it easy for teams to manage the required certificates and provisioning profiles for your iOS apps.

Appfile certificates, for example on your GitHub personal account or organization.

iOSアプリのFastlane matchを初期化します。

fastlane match init

次に、オプション #1 (Git Storage) を選択してください。

[01:00:00]: fastlane match supports multiple storage modes, please select the one you want to use:1. git2. google_cloud3. s3?

新しく作成されたリポジトリのURLを割り当てます。

[01:00:00]: Please create a new, private git repository to store the certificates and profiles there[01:00:00]: URL of the Git Repo: <YOUR_CERTIFICATES_REPO_URL>

Fastlane フォルダ内にファイル名が「Matchfile」という名前のファイルがあります。 このファイルは、証明書リポジトリのHTTPS URLに設定する必要があります。 オプションでSSHを使用することもできますが、実行するために別のステップが必要になります。 _git_url_次に、Fastlane Matchで証明書を生成し、入力されたクレデンシャルを入力してください。

# ios/Matchfilegit_url("https://github.com/gitusername/certificates")storage_mode("git")type("appstore")

__CAPGO_KEEP_0__ アクションが証明書リポジトリを復号化するために使用するパスフレーズを入力するように求められます。

You will be prompted to enter a passphrase. Remember it correctly because it will be used later by GitHub Actions to decrypt your certificates repository.

fastlane match appstore

__CAPGO_KEEP_0__ で問題が発生し、必要な権限が得られなかった場合、ご確認ください。

[01:40:52]: All required keys, certificates and provisioning profiles are installed 🙌

If you experienced any problem with GitHub and the necessary permissions, maybe this 投稿 gitの認証トークンを生成するのに役立ちます。

生成された証明書とプロビジョニング プロファイルは、証明書リポジトリのリソースにアップロードされます。

App Store Connect証明書

最後に、 project Xcodeで開き、リリース構成のアプリのプロビジョニング プロファイルを更新してください。

XCode証明書

💡いくつかの注意事項があります。

MATCH

CI/CDが証明書とプロビジョニング プロファイルをインポートするには、証明書リポジトリにアクセスする必要があります。

In GitHub, go to このように、設定パーソナル アクセス トークン → クリック Generate New Token → チェック repo スコープ → その後クリック Generate token.

パーソナル アクセス トークンを作成

__CAPGO_KEEP_0__ Actionsで証明書とプロビジョニング プロファイルをインポートするために使用されるものです。 また、__CAPGO_KEEP_1__ Secretsでvarが設定され、ファイルにハードコーディングされないようにします。 GIT_TOKEN.

環境変数のために生成されたパーソナル アクセス トークンのコピーを用意してください。後で使用します。

CERTIFICATE_STORE_URL = ENV["CERTIFICATE_STORE_URL"]
GIT_USERNAME = ENV["GIT_USERNAME"]
GIT_TOKEN = ENV["GIT_TOKEN"]
FASTLANE_APPLE_ID = ENV["FASTLANE_APPLE_ID"]

git_url(CERTIFICATE_STORE_URL)
storage_mode("git")
type("appstore")
git_basic_authorization(Base64.strict_encode64("#{GIT_USERNAME}:#{GIT_TOKEN}"))
username(FASTLANE_APPLE_ID)

This will be used by GitHub Actions to import the certificates and provisioning profiles. And var will be set in GitHub Secrets, instead of hard-coding them in the file.

このファイルは__CAPGO_KEEP_0__ Actionsで使用され、証明書とプロビジョニング プロファイルをインポートします。 また、__CAPGO_KEEP_1__ Secretsでvarが設定され、ファイルにハードコーディングされないようにします。

In GitHub Actions, __CAPGO_KEEP_0__ Actionsで 実行時間に基づいて課金されます。 App Store Connectでビルドが処理されるまでに約10-15分かかります。

個人的プロジェクトの場合、エストメートドコストパービルドは最大で $0.08/分 x 15 分 = $1.2、またはそれ以上、プロジェクトの構成または依存関係に応じて

価格設定について私と同じ懸念を持つ場合は、個人的プロジェクトの場合、 skip_waiting_for_build_processing を維持できます。 true.

何が問題か?ビルドが処理された後、ユーザーに配布するためにアプリをApp Store Connectにアップデートする必要があるのです。

このオプションは、個人的プロジェクトのビルド時間を節約するためにオプションです。フリープロジェクトの場合は、問題ありません。 を参照してください。.

3. Setup GitHub Actions

3. GitHub アクションの設定

__CAPGO_KEEP_0__ シークレットの設定 ENV 値のソースがわかりませんか?それはプロジェクトのシークレットからです。 🤦

GitHubのシークレットを設定

1. APP_STORE_CONNECT_TEAM_ID - App Store ConnectチームのIDが複数のチームに所属している場合のあなたのチームのIDです。

2. DEVELOPER_APP_ID - App Store Connectにアクセスし、 アプリ情報 → 下部にスクロールし、 General Information アプリの Apple ID.

3. DEVELOPER_APP_IDENTIFIER セクションを確認し、

4. DEVELOPER_PORTAL_TEAM_ID - アプリのバンドルIDを確認します。

5. FASTLANE_APPLE_ID - Developer PortalチームのIDが複数のチームに所属している場合のIDです。

6. GIT_USERNAME - アプリを管理するために使用するApple IDまたは開発者メールアドレスです。 GIT_TOKEN &

7. MATCH_PASSWORD - Gitユーザー名とパーソナルアクセストークンを入力してください。- matchを初期化したときに割り当てたパスフレーズが、証明書とプロビジョニングプロファイルのデコードに使用されます。

8. PROVISIONING_PROFILE_SPECIFIER - match AppStore <YOUR_APP_BUNDLE_IDENTIFIER>, 例えば。 match AppStore com.domain.blabla.demo.

9. TEMP_KEYCHAIN_USER &#x26; TEMP_KEYCHAIN_PASSWORD - ワークフロー用に一時的なキーチェーンユーザーとパスワードを割り当てます。

10. APPLE_KEY_ID — App Store Connect API キー 🔺キーID。

11. APPLE_ISSUER_ID — App Store Connect API キー 🔺発行者ID。

12. APPLE_KEY_CONTENT — App Store Connect API キー 🔺キーファイルまたはキーコンテンツ (.p8)。 確認してください。, — Match キーのリポジトリ URL (例:

13. CERTIFICATE_STORE_URL https://__CAPGO_KEEP_0__.com/***/fastlane_match.git 4. github ワークフロー ファイルを設定します。)

GitHub ワークフロー ディレクトリを作成します。

4. GitHub workflow fileを設定します。

cd .github/workflows

フォルダの中に、ファイルを「__CAPGO_KEEP_0__」と名付けて、以下の内容を追加してください。 workflow このワークフローは、各__CAPGO_KEEP_0__タグ後にトリガーされるべきです。タグを自動化する必要がある場合は、 build-upload-ios.yml「Automatic build and release with __CAPGO_KEEP_0__ actions」を参照してください。

name: Build source code on ios

on:
  push:
    tags:
      - '*'

jobs:
  build_ios:
    runs-on: macOS-latest
    steps:
      - uses: actions/checkout@v6
      - name: set Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: npm
      - name: Install dependencies
        id: install_code
        run: npm ci
      - name: Build
        id: build_code
        run: npm run build
      - uses: actions/cache@v5
        with:
          path: ios/App/Pods
          key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-pods-
      - name: Sync
        id: sync_code
        run: npx cap sync
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: 2.7.2
      - uses: maierj/fastlane-action@v2.3.0
        env:
          DEVELOPER_APP_IDENTIFIER: ${{ secrets.DEVELOPER_APP_IDENTIFIER }}
          DEVELOPER_APP_ID: ${{ secrets.DEVELOPER_APP_ID }}
          PROVISIONING_PROFILE_SPECIFIER: match AppStore ${{ secrets.DEVELOPER_APP_IDENTIFIER }}
          TEMP_KEYCHAIN_USER: ${{ secrets.TEMP_KEYCHAIN_USER }}
          TEMP_KEYCHAIN_PASSWORD: ${{ secrets.TEMP_KEYCHAIN_PASSWORD }}
          APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
          APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
          APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
          CERTIFICATE_STORE_URL: https://github.com/${{ secrets.CERTIFICATE_STORE_REPO }}.git
          GIT_USERNAME: ${{ secrets.GIT_USERNAME }}
          GIT_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
          FASTLANE_APPLE_ID: ${{ secrets.FASTLANE_APPLE_ID }}
          MATCH_USERNAME: ${{ secrets.FASTLANE_APPLE_ID }}
          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
          APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
          DEVELOPER_PORTAL_TEAM_ID: ${{ secrets.DEVELOPER_PORTAL_TEAM_ID }}
        with:
          lane: closed_beta
      - name: Upload release bundle
        uses: actions/upload-artifact@v2
        with:
          name: ios-release
          path: ./App.ipa
          retention-days: 60

This workflow should be triggered after each GitHub 各コミットを送信するたびに、TestFlightでリリースが作成されます。アプリはIonicを使用する必要はありません。ただし、__CAPGO_KEEP_0__ベースが必須であり、古いCordovaモジュールを使用しても構いませんが、__CAPGO_KEEP_1__ JSプラグインを優先することをお勧めします。 Automatic build and release with GitHub actions フォルダの中に、ファイルを「__CAPGO_KEEP_1__」と名付けて、以下の内容を追加してください。

このワークフローは、各__CAPGO_KEEP_1__タグ後にトリガーされるべきです。タグを自動化する必要がある場合は、

「Automatic build and release with __CAPGO_KEEP_1__ actions」を参照してください。

Your App doesn’t need to use Ionic, only Capacitor base is mandatory., it can have old Cordova module, but Capacitor JS plugin should be preferred.

各コミットを送信するたびに、TestFlightでリリースが作成されます。

Create a Commit

Make a commitTrigger the workflow

Trigger the workflow

Started with commit main or development Testflight Dashboard

Yes, you can deploy from your local machine.

Push the new commits to the branch

or

to trigger the workflow.

Yes, you can, and it is effortless.

Imagine that you have a private repository, and you have used up the minutes of the free plan and you do not want to pay for new releases, or maybe you prefer to submit the application manually.

Let's go for it

Ok, first we need to create in my_project_path/fastlane path a file called .env, just in the same path as Fastfile, to be able to create the same secret properties found in our _GitHub, a_s below:

.envファイルからローカルマシンからデプロイ

今、ローカルマシンからデプロイするための terminal と、ローカルマシンからデプロイするための Fastlane を起動してください:

fastlane closed_beta

❌ .envファイルについての重要なこと 、このデータを公開したくないので、.gitignore に追加する必要があります、例えば: ❌ ローカルマシンで実行する場合と同じように動作するはずです。🍻

fastlane/*.env

GitHub

Local Fastlane run

Terminal execution: $ Fastlane closed_beta

このまでに到達した場合、FastlaneとGitHub Actionsを使用してiOSアプリの完全自動化プロセスを獲得したことに対して、我々はあなたに祝福します。

各コミットを送信するたびに、Google Playコンソールのベータチャンネルでリリースが作成されます。 martin@capgo.app

martin@__CAPGO_KEEP_0__.app

デバイス上でビルド まだデバイス上でビルドする必要がある場合は、手動でプロビジョニングに追加する必要があります。
デバイスをMacに接続し、デバイスメニューを開きます デバイスiOSメニュー 次に、識別子をコピーしてください 識別子iOS fastlane register_new_device 次に、以下のコマンドを実行してください: 識別子を設定(iOS)

問題が発生した場合

開発用デバイスでテストできないなど問題が発生した場合、通常はその問題を解決することができます。

あなたを救う魔法のコマンドがあります:

fastlane match nuke development
fastlane match development

次を実行してください: プロジェクトをクリーンするにはShift(⇧)+Command(⌘)を押しながらKを押すか、Product > Clean(クリーンビルドフォルダ)とラベル付けされている場合もあります。

次に、デバイス上でアプリを再度実行してください。

ありがとうございます

この記事は以下の記事に基づいています:

自動的なCapacitoriOSビルドから続けてください。GitHubアクションを使用してください

Capgoを使用している場合 自動的なCapacitor IOSビルドとGitHubアクションを使用して、match CI/CDの自動化を計画するには、__CAPGO_KEEP_0__ CI/CDに接続する Capgo CI/CD for the product workflow in Capgo CI/CD, Capgo Native Builds for the product workflow in Capgo Native Builds, Capgo Integrations for the product workflow in Capgo Integrations, CI/CDの統合 CI/CDの実装詳細 GitHub Actions Integration GitHub の実装詳細のアクション統合のために。

Capacitor アプリのリアルタイム更新

Capgo を使用して、ウェブ層のバグが生じた場合、App Store の承認待ちを数日間省略して修正を配信することができます。ユーザーはバックグラウンドで更新を受け取り、ネイティブの変更は通常のレビュー経路を通じて実行されます。

今すぐ始める

最新のブログ記事

Capgoは、プロフェッショナルなモバイルアプリを作成するために必要な最良の洞察を提供します。