{"id":193,"date":"2026-03-09T10:39:17","date_gmt":"2026-03-09T10:39:17","guid":{"rendered":"https:\/\/blog.rebalai.com\/ja\/2026\/03\/09\/setting-up-github-actions-for-python-applications\/"},"modified":"2026-03-09T22:00:16","modified_gmt":"2026-03-09T22:00:16","slug":"setting-up-github-actions-for-python-applications","status":"publish","type":"post","link":"https:\/\/blog.rebalai.com\/ja\/2026\/03\/09\/setting-up-github-actions-for-python-applications\/","title":{"rendered":"Python\u30a2\u30d7\u30ea\u306eGitHub Actions\u5b8c\u5168\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7: 2\u9031\u9593\u8a66\u884c\u932f\u8aa4\u3057\u3066\u5b66\u3093\u3060\u3053\u3068"},"content":{"rendered":"<p>\u53bb\u5e74\u306e\u79cb\u30013\u4eba\u30c1\u30fc\u30e0\u3067\u958b\u767a\u3057\u3066\u3044\u308bFastAPI\u30a2\u30d7\u30ea\u306eCI\u3092CircleCI\u304b\u3089GitHub Actions\u306b\u79fb\u884c\u3057\u305f\u3002\u7406\u7531\u306f\u30b7\u30f3\u30d7\u30eb\u3067\u3001CircleCI\u306e\u6708\u984d\u304c3\u4eba\u898f\u6a21\u306e\u30c1\u30fc\u30e0\u306b\u306f\u91cd\u304f\u306a\u3063\u3066\u304d\u305f\u3053\u3068\u3001\u3042\u3068\u30b3\u30fc\u30c9\u3082PR\u3082GitHub\u4e0a\u3067\u7ba1\u7406\u3057\u3066\u3044\u308b\u306e\u306b\u3001CI\u3060\u3051\u5225\u30b5\u30fc\u30d3\u30b9\u3092\u4f7f\u3046\u610f\u5473\u3092\u611f\u3058\u306a\u304f\u306a\u3063\u3066\u304d\u305f\u304b\u3089\u3002<\/p>\n<p>\u79fb\u884c\u306b2\u9031\u9593\u304b\u304b\u3063\u305f\u3002\u300c\u9031\u672b\u3067\u30b5\u30af\u30c3\u3068\u7d42\u308f\u308b\u300d\u3068\u601d\u3063\u3066\u3044\u305f\u306e\u306b\u3001\u30ad\u30e3\u30c3\u30b7\u30e5\u3068secrets\u5468\u308a\u3067\u60f3\u5b9a\u5916\u306e\u554f\u984c\u306b\u7acb\u3066\u7d9a\u3051\u306b\u30cf\u30de\u3063\u305f\u3002\u3053\u306e\u8a18\u4e8b\u306f\u305d\u306e\u8a18\u9332\u3067\u3082\u3042\u308a\u3001\u6700\u7d42\u7684\u306b\u843d\u3061\u7740\u3044\u305f\u69cb\u6210\u306e\u89e3\u8aac\u3067\u3082\u3042\u308b\u3002<\/p>\n<h2>CircleCI\u304b\u3089\u306e\u79fb\u884c: \u6700\u521d\u306e30\u5206\u3067\u3069\u3053\u307e\u3067\u52d5\u304f\u304b<\/h2>\n<p>GitHub Actions\u306e\u6700\u5c0f\u69cb\u6210\u306f\u3001\u6b63\u76f4\u3073\u3063\u304f\u308a\u3059\u308b\u304f\u3089\u3044\u30b7\u30f3\u30d7\u30eb\u3060\u3002<code>.github\/workflows\/ci.yml<\/code>\u3092\u4f5c\u308b\u3060\u3051\u3067\u52d5\u304d\u59cb\u3081\u308b\u3002<\/p>\n<pre><code class=\"language-yaml\">name: CI\n\non:\n  push:\n    branches: [main, develop]\n  pull_request:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Python 3.12\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\n        uses: actions\/setup-python@v5\n        with:\n          python-version: &quot;3.12&quot;\n\n      - name: \u4f9d\u5b58\u95a2\u4fc2\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.txt\n          pip install -r requirements-dev.txt\n\n      - name: \u30c6\u30b9\u30c8\u5b9f\u884c\n        run: pytest tests\/ -v\n<\/code><\/pre>\n<p>\u3053\u308c\u3067\u52d5\u304f\u3002\u672c\u5f53\u306b\u3053\u308c\u3060\u3051\u3002CircleCI\u3060\u3068<code>config.yml<\/code>\u306e\u69cb\u6587\u3092\u899a\u3048\u306a\u304c\u3089Orbs\u3092\u8abf\u3079\u306a\u304c\u3089\u3001\u3068\u3044\u3046\u611f\u3058\u3060\u3063\u305f\u3051\u3069\u3001GitHub Actions\u306f\u6700\u521d\u306e30\u5206\u3067\u30c6\u30b9\u30c8\u304c\u901a\u3063\u305f\u3002<\/p>\n<p>\u305f\u3060\u3057\u3001\u3053\u308c\u3060\u3068Python 3.12\u3067\u3057\u304b\u52d5\u4f5c\u78ba\u8a8d\u3067\u304d\u306a\u3044\u3002\u3046\u3061\u306e\u30a2\u30d7\u30ea\u306fAWS Lambda\u306b\u30c7\u30d7\u30ed\u30a4\u3057\u3066\u3044\u3066\u3001\u672c\u756a\u74b0\u5883\u304c\u5fc5\u305a\u3057\u3082\u6700\u65b0\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u8ffd\u3044\u304b\u3051\u3066\u3044\u308b\u308f\u3051\u3058\u3083\u306a\u3044\u3002\u306a\u306e\u3067matrix testing\u304c\u5fc5\u8981\u306b\u306a\u3063\u305f\u3002<\/p>\n<h2>Matrix Testing\u306e\u7f60: <code>fail-fast<\/code>\u3092\u5fd8\u308c\u3066\u7121\u99c4\u306b\u6642\u9593\u3092\u6eb6\u304b\u3057\u305f\u8a71<\/h2>\n<p>\u8907\u6570\u306ePython\u30d0\u30fc\u30b8\u30e7\u30f3\u3067\u30c6\u30b9\u30c8\u3059\u308b\u306b\u306f<code>strategy.matrix<\/code>\u3092\u4f7f\u3046\u3002<\/p>\n<pre><code class=\"language-yaml\">jobs:\n  test:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        python-version: [&quot;3.10&quot;, &quot;3.11&quot;, &quot;3.12&quot;]\n      fail-fast: false  # \u2190 \u3053\u308c\u3092\u5fd8\u308c\u308b\u3068\u5f8c\u6094\u3059\u308b\n\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Python ${{ matrix.python-version }}\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\n        uses: actions\/setup-python@v5\n        with:\n          python-version: ${{ matrix.python-version }}\n\n      - name: \u4f9d\u5b58\u95a2\u4fc2\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\n        run: |\n          pip install -r requirements.txt\n          pip install -r requirements-dev.txt\n\n      - name: lint (ruff)\n        run: ruff check .\n\n      - name: \u578b\u30c1\u30a7\u30c3\u30af (mypy)\n        run: mypy app\/ --ignore-missing-imports\n\n      - name: \u30c6\u30b9\u30c8\u5b9f\u884c\n        run: pytest tests\/ -v --tb=short\n<\/code><\/pre>\n<p><code>fail-fast: false<\/code>\u3092\u8a2d\u5b9a\u3057\u306a\u3044\u3068\u3001Python 3.10\u306e\u30b8\u30e7\u30d6\u304c\u5931\u6557\u3057\u305f\u77ac\u9593\u306b3.11\u30683.12\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u308b\u3002\u6700\u521d\u3053\u308c\u3092\u5fd8\u308c\u3066\u30013.10\u306e\u554f\u984c\u3092\u76f4\u3057\u305f\u3068\u601d\u3063\u305f\u3089\u5b9f\u306f3.11\u3067\u3082\u5225\u306e\u554f\u984c\u304c\u3042\u3063\u305f\u3001\u3068\u3044\u3046\u72b6\u6cc1\u306b\u306a\u3063\u305f\u3002\u5168\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u7d50\u679c\u3092\u4e00\u5ea6\u306b\u898b\u305f\u3044\u306a\u3089\u5fc5\u9808\u306e\u8a2d\u5b9a\u3060\u3002<\/p>\n<p><code>continue-on-error<\/code>\u3068\u3044\u3046\u8a2d\u5b9a\u3082\u3042\u308b\u3002\u3053\u308c\u3092matrix\u306e\u7279\u5b9aitem\u306b\u8a2d\u5b9a\u3059\u308b\u3068\u3001\u305d\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u5931\u6557\u3057\u3066\u3082\u30ef\u30fc\u30af\u30d5\u30ed\u30fc\u5168\u4f53\u3092\u6210\u529f\u6271\u3044\u306b\u3067\u304d\u308b\u3002Python 3.13\u306ebeta\u7248\u3067\u30c6\u30b9\u30c8\u3057\u305f\u3044\u3051\u3069CI\u3092\u8d64\u306b\u3057\u305f\u304f\u306a\u3044\u3001\u3068\u3044\u3046\u5834\u5408\u306b\u4fbf\u5229\u3002\u305f\u3060\u3001\u79c1\u306f\u3042\u307e\u308a\u4f7f\u3063\u3066\u3044\u306a\u3044\u3002\u5931\u6557\u306f\u5931\u6557\u3068\u3057\u3066\u898b\u305f\u3044\u6d3e\u306a\u306e\u3067\u3002<\/p>\n<p>\u305d\u3046\u3044\u3048\u3070\u3001matrix\u3092\u4f7f\u3046\u3068\u30b8\u30e7\u30d6\u6570\u304c\u5897\u3048\u308b\u306e\u3067\u3001GitHub Actions\u306e\u7121\u6599\u67a0(\u67082000\u5206\u3001\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u5834\u5408)\u304c\u601d\u3063\u305f\u3088\u308a\u901f\u304f\u6e1b\u308b\u30023\u30d0\u30fc\u30b8\u30e7\u30f3\u00d7\u5e73\u57473\u5206=9\u5206\/PR\u3068\u3044\u3046\u306e\u306f\u5730\u5473\u306b\u52b9\u3044\u3066\u304f\u308b\u3002\u3053\u308c\u306f\u30ad\u30e3\u30c3\u30b7\u30e5\u3067\u89e3\u6c7a\u3067\u304d\u308b\u3002<\/p>\n<h2>pip-cache\u306e\u30ad\u30fc\u8a2d\u8a08\u3092\u9593\u9055\u3048\u3066\u30d3\u30eb\u30c9\u304c\u9045\u304f\u306a\u3063\u305f\u8a71<\/h2>\n<p>\u6700\u521d\u306b\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u8a2d\u5b9a\u3057\u305f\u3068\u304d\u3001\u3053\u3046\u66f8\u3044\u305f:<\/p>\n<pre><code class=\"language-yaml\">- name: pip\u30ad\u30e3\u30c3\u30b7\u30e5\n  uses: actions\/cache@v4\n  with:\n    path: ~\/.cache\/pip\n    key: ${{ runner.os }}-pip-${{ hashFiles('**\/requirements*.txt') }}\n    restore-keys: |\n      ${{ runner.os }}-pip-\n<\/code><\/pre>\n<p>\u3053\u308c\u3067\u52d5\u3044\u305f\u3002\u6700\u521d\u306f\u3002<\/p>\n<p>\u554f\u984c\u306f<code>requirements.txt<\/code>\u3068<code>requirements-dev.txt<\/code>\u3092\u5225\u7ba1\u7406\u3057\u3066\u3044\u305f\u3053\u3068\u3002<code>hashFiles('**\/requirements*.txt')<\/code>\u306f\u3069\u3061\u3089\u3082\u542b\u3080\u306e\u3067\u4e00\u898b\u3088\u3055\u305d\u3046\u306a\u3093\u3060\u3051\u3069\u3001<code>requirements-dev.txt<\/code>\u3060\u3051\u5909\u308f\u3063\u305f\u3068\u304d\u306b<code>requirements.txt<\/code>\u306e\u30ad\u30e3\u30c3\u30b7\u30e5\u3082\u7121\u52b9\u5316\u3055\u308c\u308b\u3002\u9006\u3082\u7136\u308a\u3002<\/p>\n<p>2\u9031\u9593\u5f8c\u3001pytest\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u4e0a\u3052\u3088\u3046\u3068\u3057\u3066<code>requirements-dev.txt<\/code>\u30921\u884c\u5909\u66f4\u3057\u305f\u3089\u3001\u5168matrix\u3067\u4f9d\u5b58\u95a2\u4fc2\u306e\u518d\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u304c\u8d70\u3063\u305f\u30023\u30d0\u30fc\u30b8\u30e7\u30f3\u5206\u3002\u305d\u306e\u3068\u304d\u521d\u3081\u3066\u300c\u3042\u3001\u3053\u308c\u306f\u8a2d\u8a08\u304c\u9593\u9055\u3063\u3066\u3044\u305f\u300d\u3068\u6c17\u3065\u3044\u305f\u2014\u2014\u3057\u304b\u3082\u539f\u56e0\u306f\u5358\u7d14\u3067\u3001<code>actions\/setup-python<\/code>\u81ea\u4f53\u306b\u30ad\u30e3\u30c3\u30b7\u30e5\u6a5f\u80fd\u304c\u3042\u308b\u3053\u3068\u3092\u898b\u843d\u3068\u3057\u3066\u3044\u305f\u3060\u3051\u3060\u3063\u305f\u3002<\/p>\n<p>\u76f4\u3057\u305f\u5f8c\u306e\u8a2d\u5b9a\u306f\u3053\u308c\u3060\u3051:<\/p>\n<pre><code class=\"language-yaml\">- name: Python ${{ matrix.python-version }}\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\n  uses: actions\/setup-python@v5\n  with:\n    python-version: ${{ matrix.python-version }}\n    cache: 'pip'                      # \u3053\u308c\u3060\u3051\u3067OK\n    cache-dependency-path: |\n      requirements.txt\n      requirements-dev.txt\n<\/code><\/pre>\n<p><code>actions\/setup-python@v4<\/code>\u4ee5\u964d\u306f\u3053\u306e<code>cache<\/code>\u30aa\u30d7\u30b7\u30e7\u30f3\u304c\u4f7f\u3048\u3066\u3001\u5185\u90e8\u3067Python\u30d0\u30fc\u30b8\u30e7\u30f3\u3068requirements\u30d5\u30a1\u30a4\u30eb\u306e\u30cf\u30c3\u30b7\u30e5\u3092\u7d44\u307f\u5408\u308f\u305b\u305f\u30ad\u30fc\u3092\u81ea\u52d5\u751f\u6210\u3057\u3066\u304f\u308c\u308b\u3002<code>actions\/cache<\/code>\u3092\u624b\u52d5\u3067\u66f8\u304f\u3088\u308a\u7ba1\u7406\u304c\u697d\u3067\u3001\u3057\u304b\u3082\u3088\u308a\u8ce2\u3044\u3002<\/p>\n<p>\u30d3\u30eb\u30c9\u6642\u9593\u306e\u5909\u5316: \u30ad\u30e3\u30c3\u30b7\u30e5\u306a\u3057\u3067\u5e73\u57474\u520612\u79d2 \u2192 \u30ad\u30e3\u30c3\u30b7\u30e5\u30d2\u30c3\u30c8\u664238\u79d2\u3002\u3053\u308c\u306f\u4f53\u611f\u304c\u304b\u306a\u308a\u9055\u3046\u3002<\/p>\n<h2><code>GITHUB_TOKEN<\/code>\u3068\u81ea\u524dSecrets\u306e\u4f7f\u3044\u5206\u3051 \u2014 \u3053\u3053\u304c\u4e00\u756a\u30cf\u30de\u3063\u305f<\/h2>\n<p>\u6b63\u76f4\u3053\u308c\u304c\u4e00\u756a\u6642\u9593\u3092\u4f7f\u3063\u305f\u3002GitHub\u306b\u306f<code>GITHUB_TOKEN<\/code>\u3068\u3044\u3046\u30b7\u30fc\u30af\u30ec\u30c3\u30c8\u304c\u81ea\u52d5\u3067\u7528\u610f\u3055\u308c\u3066\u3044\u3066\u3001\u30ea\u30dd\u30b8\u30c8\u30ea\u3078\u306e\u66f8\u304d\u8fbc\u307f\u3084Issue\u3078\u306e\u30b3\u30e1\u30f3\u30c8\u306a\u3069\u304c\u3067\u304d\u308b\u3002\u3053\u308c\u306f\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u8a2d\u5b9a\u304b\u3089\u6a29\u9650\u3092\u8abf\u6574\u3067\u304d\u308b\u3002<\/p>\n<p>\u4e00\u65b9\u3001AWS Lambda\u306b\u30c7\u30d7\u30ed\u30a4\u3059\u308b\u306b\u306fAWS\u306e\u8a8d\u8a3c\u60c5\u5831\u304c\u5fc5\u8981\u3067\u3001\u3053\u308c\u306f\u81ea\u5206\u3067\u30ea\u30dd\u30b8\u30c8\u30ea\u306eSecrets\u306b\u767b\u9332\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u3002\u6700\u521d\u306f\u3053\u3046\u3044\u3046\u69cb\u6210\u306b\u3057\u3066\u3044\u305f:<\/p>\n<pre><code class=\"language-yaml\">- name: AWS Lambda\u306b\u30c7\u30d7\u30ed\u30a4\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    AWS_DEFAULT_REGION: ap-northeast-1\n  run: |\n    aws lambda update-function-code \\\n      --function-name my-fastapi-app \\\n      --zip-file fileb:\/\/deployment.zip\n<\/code><\/pre>\n<p>\u554f\u984c\u306f\u3053\u306e\u30b9\u30c6\u30c3\u30d7\u3092PR\u306epush\u3067\u3082\u5b9f\u884c\u3057\u3066\u3044\u305f\u3053\u3068\u3002PR\u4f5c\u6210\u306e\u305f\u3073\u306bLambda\u304c\u4e0a\u66f8\u304d\u3055\u308c\u308b\u3002\u91d1\u66dc\u306e\u5348\u5f8c\u306b\u3053\u308c\u306b\u6c17\u3065\u3044\u3066\u3001\u304b\u306a\u308a\u6025\u3044\u3067\u4fee\u6b63\u3057\u305f\u3002<\/p>\n<p>\u6761\u4ef6\u3092\u8ffd\u52a0\u3059\u308c\u3070\u89e3\u6c7a\u3067\u304d\u308b:<\/p>\n<pre><code class=\"language-yaml\">- name: AWS Lambda\u306b\u30c7\u30d7\u30ed\u30a4 (main\u3078\u306epush\u306e\u307f)\n  if: github.ref == 'refs\/heads\/main' &amp;&amp; github.event_name == 'push'\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    AWS_DEFAULT_REGION: ap-northeast-1\n  run: |\n    aws lambda update-function-code \\\n      --function-name my-fastapi-app \\\n      --zip-file fileb:\/\/deployment.zip\n<\/code><\/pre>\n<p>\u4eca\u306fOIDC\u8a8d\u8a3c\u306b\u79fb\u884c\u3057\u3066\u3044\u3066\u3001\u30a2\u30af\u30bb\u30b9\u30ad\u30fc\u3092Secrets\u306b\u7f6e\u3044\u3066\u3044\u306a\u3044\u3002OIDC\u3092\u4f7f\u3046\u3068GitHub Actions\u304cAWS\u306b\u5bfe\u3057\u3066IAM\u30ed\u30fc\u30eb\u3092\u4e00\u6642\u7684\u306b\u5f15\u304d\u53d7\u3051\u308b\u5f62\u306b\u306a\u308b\u306e\u3067\u3001\u9577\u671f\u9593\u6709\u52b9\u306a\u8a8d\u8a3c\u60c5\u5831\u3092\u3069\u3053\u306b\u3082\u4fdd\u5b58\u3057\u306a\u304f\u3066\u6e08\u3080\u3002\u8a2d\u5b9a\u306f\u5c11\u3057\u8907\u96d1\u3060\u3051\u3069\u3001\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u306e\u89b3\u70b9\u304b\u3089\u306f\u660e\u3089\u304b\u306b\u3053\u3061\u3089\u304c\u6b63\u3057\u3044\u3002<\/p>\n<p><code>GITHUB_TOKEN<\/code>\u306e\u6a29\u9650\u306b\u3064\u3044\u3066\u3082\u4e00\u70b9\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u5e83\u3081\u306e\u6a29\u9650\u304c\u4ed8\u4e0e\u3055\u308c\u3066\u3044\u308b\u30ea\u30dd\u30b8\u30c8\u30ea\u3082\u3042\u308b\u3002\u30ef\u30fc\u30af\u30d5\u30ed\u30fc\u30d5\u30a1\u30a4\u30eb\u306e\u5148\u982d\u3067\u660e\u793a\u7684\u306b\u6700\u5c0f\u9650\u306e\u6a29\u9650\u3060\u3051\u3092\u5ba3\u8a00\u3059\u308b\u7fd2\u6163\u3092\u3064\u3051\u305f\u65b9\u304c\u3044\u3044:<\/p>\n<pre><code class=\"language-yaml\">permissions:\n  contents: read  # \u30b3\u30fc\u30c9\u306e\u8aad\u307f\u53d6\u308a\u3060\u3051\n<\/code><\/pre>\n<h2>\u5b9f\u969b\u306b\u672c\u756a\u30673\u30f6\u6708\u52d5\u3044\u3066\u3044\u308bworkflow.yml\u5168\u6587<\/h2>\n<p>2\u9031\u9593\u306e\u8a66\u884c\u932f\u8aa4\u3092\u7d4c\u3066\u3001\u4eca\u3046\u3061\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u3042\u308b\u306e\u306f\u3053\u308c\u3060:<\/p>\n<pre><code class=\"language-yaml\">name: CI\/CD\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\npermissions:\n  contents: read\n\njobs:\n  test:\n    name: \u30c6\u30b9\u30c8 (Python ${{ matrix.python-version }})\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        python-version: [&quot;3.10&quot;, &quot;3.11&quot;, &quot;3.12&quot;]\n      fail-fast: false\n\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Python ${{ matrix.python-version }}\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\n        uses: actions\/setup-python@v5\n        with:\n          python-version: ${{ matrix.python-version }}\n          cache: 'pip'\n          cache-dependency-path: |\n            requirements.txt\n            requirements-dev.txt\n\n      - name: \u4f9d\u5b58\u95a2\u4fc2\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\n        run: |\n          pip install -r requirements.txt\n          pip install -r requirements-dev.txt\n\n      - name: lint (ruff)\n        run: ruff check . --output-format=github  # PR\u4e0a\u3067\u30d5\u30a1\u30a4\u30eb\u3068\u884c\u756a\u53f7\u3092\u76f4\u63a5\u8868\u793a\n\n      - name: \u578b\u30c1\u30a7\u30c3\u30af (mypy)\n        run: mypy app\/ --ignore-missing-imports\n\n      - name: \u30c6\u30b9\u30c8\u5b9f\u884c\n        run: pytest tests\/ -v --tb=short --cov=app --cov-report=xml\n\n  deploy:\n    name: \u30c7\u30d7\u30ed\u30a4 (main\u306e\u307f)\n    needs: test  # test\u30b8\u30e7\u30d6\u304c\u5168\u90e8\u901a\u3063\u3066\u304b\u3089\u5b9f\u884c\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs\/heads\/main' &amp;&amp; github.event_name == 'push'\n\n    permissions:\n      contents: read\n      id-token: write  # OIDC\u8a8d\u8a3c\u306b\u5fc5\u8981\n\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: AWS\u306e\u8a8d\u8a3c (OIDC)\n        uses: aws-actions\/configure-aws-credentials@v4\n        with:\n          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}\n          aws-region: ap-northeast-1\n\n      - name: \u30c7\u30d7\u30ed\u30a4\u30d1\u30c3\u30b1\u30fc\u30b8\u4f5c\u6210\n        run: |\n          pip install -r requirements.txt -t .\/package\n          cp -r app\/ .\/package\/\n          cd package &amp;&amp; zip -r ..\/deployment.zip .\n\n      - name: Lambda\u66f4\u65b0\n        run: |\n          aws lambda update-function-code \\\n            --function-name my-fastapi-app \\\n            --zip-file fileb:\/\/deployment.zip\n<\/code><\/pre>\n<p><code>ruff check<\/code>\u306b<code>--output-format=github<\/code>\u3092\u6e21\u3057\u3066\u3044\u308b\u306e\u306f\u5730\u5473\u306a\u30dd\u30a4\u30f3\u30c8\u3067\u3001\u3053\u308c\u3092\u3064\u3051\u308b\u3068lint\u30a8\u30e9\u30fc\u304cGitHub\u4e0a\u306e\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u306b\u6ce8\u91c8\u3068\u3057\u3066\u8868\u793a\u3055\u308c\u308b\u3002PR\u4e0a\u3067\u3069\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u4f55\u884c\u76ee\u304c\u554f\u984c\u304b\u304c\u4e00\u76ee\u3067\u308f\u304b\u3063\u3066\u3001\u30ec\u30d3\u30e5\u30fc\u306e\u624b\u9593\u304c\u6e1b\u3063\u305f\u3002<\/p>\n<hr \/>\n<p>\u65b0\u3057\u3044Python\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306bGitHub Actions\u3092\u8a2d\u5b9a\u3059\u308b\u306a\u3089\u3001\u79c1\u306f\u3053\u306e\u9806\u756a\u3067\u3084\u308b\u3053\u3068\u3092\u3059\u3059\u3081\u308b: \u307e\u305a\u6700\u5c0f\u69cb\u6210(checkout + setup-python + pip install + pytest)\u3067\u52d5\u304b\u3059\u3002\u6b21\u306bmatrix + \u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0\u3059\u308b\u3002\u6700\u5f8c\u306b\u30c7\u30d7\u30ed\u30a4\u3092\u5225job\u3068\u3057\u3066\u8ffd\u52a0\u3059\u308b\u3002<\/p>\n<p>\u4e00\u6c17\u306b\u5168\u90e8\u8a2d\u5b9a\u3057\u3088\u3046\u3068\u3059\u308b\u3068\u3001\u3069\u3053\u3067\u8a70\u307e\u3063\u305f\u304b\u308f\u304b\u3089\u306a\u304f\u306a\u308b\u3002\u79c1\u304c\u305d\u308c\u3092\u3084\u3063\u30662\u9031\u9593\u304b\u304b\u3063\u305f\u3002\u6bb5\u968e\u7684\u306b\u3084\u308c\u30703\u65e5\u3067\u7d42\u308f\u308b\u3068\u601d\u3046\u3002<\/p>\n<p><!-- Reviewed: 2026-03-09 | Status: ready_to_publish | Changes: expanded meta_description to ~158 chars; removed English filler \"Right,\" replaced with natural Japanese transition; added em-dash aside in cache section; clarified free tier is for private repos; minor phrasing tightened throughout --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u53bb\u5e74\u306e\u79cb\u30013\u4eba\u30c1\u30fc\u30e0\u3067\u958b\u767a\u3057\u3066\u3044\u308bFastAPI\u30a2\u30d7\u30ea\u306eCI\u3092CircleCI\u304b\u3089GitHub Actions\u306b\u79fb\u884c\u3057\u305f\u3002\u7406\u7531\u306f\u30b7\u30f3\u30d7\u30eb\u3067\u3001CircleCI\u306e\u6708\u984d\u304c3\u4eba\u898f\u6a21\u306e\u30c1\u30fc\u30e0\u306b\u306f\u91cd\u304f\u306a\u3063\u3066\u304d\u305f\u3053\u3068\u3001\u3042\u3068\u30b3\u30fc\u30c9\u3082PR\u3082GitHub\u4e0a\u3067\u7ba1\u7406\u3057\u3066\u3044\u308b\u306e\u306b\u3001CI\u3060\u3051\u5225\u30b5\u30fc\u30d3\u30b9\u3092\u4f7f\u3046\u610f\u5473\u3092\u611f\u3058\u306a\u304f\u306a\u3063\u3066\u304d\u305f\u304b\u3089\u3002<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-193","post","type-post","status-publish","format-standard","hentry","category-general"],"_links":{"self":[{"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/posts\/193","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/comments?post=193"}],"version-history":[{"count":1,"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/posts\/193\/revisions"}],"predecessor-version":[{"id":220,"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/posts\/193\/revisions\/220"}],"wp:attachment":[{"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/media?parent=193"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/categories?post=193"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rebalai.com\/ja\/wp-json\/wp\/v2\/tags?post=193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}