TECH PLAY

サイオステクノロジー(Tech.Lab)

サイオステクノロジー(Tech.Lab) の技術ブログ

546

はじめに 前回の記事では、GitLabとOpenShift、Gatekeeperを組み合わせたDevSecOpsモデルケース環境の構築方法を紹介しました。   本記事では、それらを組み合わせて閉域環境におけるDevSecOpsモデルケースを構築し、デモアプリを使ってCI/CDの流れにセキュリティがどのように組み込まれるのかを確認します。   金融や公共分野など高いセキュリティ要件が求められるシステムでは、インターネット非接続の環境であっても、開発のスピードと安全性を両立することが求められます。 GitLabとGatekeeperを活用することで、この課題をどのように解決できるのかを具体的に示すのが今回の目的です。 DevSecOpsとは、DevOpsの迅速な開発・運用プロセスに「セキュリティ」を組み込み、スピードと安全性を両立させる手法です。従来は「開発が完了した後にセキュリティチェックを行う」ことが一般的でした。しかしこの方法では、最終段階で脆弱性が見つかった際に大きな修正が必要となり、時間やコストの増大、リリースの遅延を招いてしまいます。 DevSecOpsでは、開発ライフサイクルの各段階にセキュリティを統合することで、早い段階からリスクを検知し、小規模な修正で対処できます。その結果、開発のスピードを維持しながら、コスト削減と安全性の向上を同時に実現できます。 DevSecOpsは、下図のように開発(Dev)と運用(Ops)のライフサイクルにセキュリティ(Sec)を組み込む考え方です。 DevSecOpsの詳細については以下の記事で解説していますので、ご参照ください。 DevSecOpsとは?安全性とスピードを両立する開発手法 | SIOS Tech. Lab 本記事のデモは、以下の流れで進めます。 ゴール 本記事のゴールは次のとおりです。 DevSecOpsのライフサイクルを実際のCI/CDパイプラインを通じて理解する GitLabとGatekeeperを組み合わせたセキュリティ統制の仕組みを把握する 前提条件 本記事のデモンストレーションは、以下の環境を前提としています。 GitLab サーバー(ソースコード管理・CI/CD実行) OpenShift クラスター(閉域環境にて構築済み、アプリケーション実行環境) GitLab Runner(OpenShift 内にデプロイ済み) Gatekeeper(OpenShift 内にデプロイ済み、リソース作成許可ポリシーを定義済み) 踏み台サーバー(クラスターへのアクセス用) これらは前回の記事「 構築編 」で構築したモデルケース環境に含まれています。 構築手順の詳細は「構築編」を参照してください。 デモアプリの仕様 ベースイメージ:nginx サービス提供ポート:8080 到達性:内部ネットワークのみアクセス可能(外部公開なし) デプロイ方式:Helm(Chart・valuesでイメージタグを切り替え) デモで使用するタグ:v1.0(初回デプロイ)、v1.1(修正デプロイ) パイプラインの実行フロー 今回利用するCI/CDパイプラインの実行フローは以下の通りです。 ビルド用パイプライン実行フロー 開発者がGitLabのビルド用プロジェクトにブランチをマージ マージをトリガーとして、GitLab CI/CDパイプラインが起動 GitLab CI/CDからOpenShiftクラスター内のGitLab Runnerへビルドジョブ実行リクエストを送信 RunnerがジョブPodを起動 ジョブPodがビルド用プロジェクトからアプリのソースコードをClone ジョブPodがdocker CLIなどを利用してコンテナイメージをビルド ジョブPodがビルドしたイメージをGitLabのビルド用プロジェクト内のレジストリにpush デプロイ用パイプライン実行フロー 開発者がGitLabのデプロイ用プロジェクトにブランチをマージ マージをトリガーとして、GitLab CI/CDパイプラインが起動 GitLab CI/CDからOpenShiftクラスター内のGitLab Runnerへデプロイジョブ実行リクエストを送信 RunnerがジョブPodを起動 ジョブPodがOpenShiftのAPIサーバーに対し、リソースのデプロイリクエストを送信 APIサーバーがGitLabのレジストリからアプリのイメージをpull APIサーバーがOpenShiftクラスター内にアプリをデプロイ DevSecOpsのデモンストレーション ここからは、構築済みのモデルケース環境を使って、実際にDevSecOpsの流れを確認します。 以下のように、アプリのデプロイを2回繰り返し、最後にGatekeeperによる制御を体験します。 アプリの初回アップロード(v1.0 デプロイ) アプリを修正して再度デプロイ(v1.1 デプロイ) Gatekeeperによる不正リソース作成の拒否 アプリケーションの初回デプロイ ここからは、DevSecOpsライフサイクルのCode → Operate(1週目)に対応します。 まず、アプリの初回デプロイを行います。 コードを ビルド用プロジェクト のfeatureブランチにpushし、developブランチへマージします。 developブランチにマージすると、コンテナイメージをビルドするパイプラインが起動します。 この操作によって、開発用のイメージ(dev-v1.0)がビルドされます。  続いて、 デプロイ用プロジェクト のfeatureブランチをdevelop ブランチへマージします。 これにより、先ほどビルドされたv1.0イメージを利用して、開発用Namespaceにアプリがデプロイされます。 $ oc get pod -n devsecops-develop -l app="nginx" NAME                                READY   STATUS    RESTARTS   AGE nginx-deployment-5d75b659c5-cqbqp   1/1     Running   0          118s 動作確認が完了したら、ビルド用プロジェクトのdevelopブランチからmainブランチへのマージリクエストを作成し、承認後にマージします。 mainブランチにマージすると、パイプラインが起動し、prod-v1.0イメージがレジストリに格納されます。 次にデプロイ用プロジェクトでdevelopブランチをmainブランチにマージすると、パイプラインが起動し、本番環境用のネームスペースにアプリをデプロイします。 その結果、本番環境にアプリがデプロイされ、表示内容を確認できれば、 Code → Operate の1週目(v1.0)が完了 です。 $ oc get pod -n devsecops-production -l app="nginx" NAME                                READY   STATUS    RESTARTS   AGE nginx-deployment-6c49676b47-m96pf   1/1     Running   0          29s nginx-deployment-6c49676b47-pzv96   1/1     Running   0          29s アプリケーションを修正して再度デプロイ ここからは、DevSecOpsライフサイクルのCode → Operate(2週目)に対応します。 アプリを修正します。ここではindex.htmlの内容を更新し、あわせて.gitlab-ci.ymlで定義しているコンテナイメージのタグをv1.1に変更します。 次に、 ビルド用プロジェクト のfeatureブランチにpushし、developブランチへマージします。 この操作によって、新しい開発用イメージ(v1.1)がビルドされます。 続いて、 デプロイ用プロジェクト のfeatureブランチでConfig/develop-values.yamlと Config/product-values.yamlのtagを修正し、反映します。その後、同様にdevelopブランチ へマージして変更を適用します。 これにより、先ほどビルドされたv1.1イメージを利用して、開発用Namespaceにアプリがデプロイされます。 $ oc describe pod -n devsecops-develop nginx-deployment-54d94596b6-8j8w6 | grep "Image:"     Image:          registry.gitlab.local.example.com/devsecops-user/devsecops-build-project/nginx:dev-v1.1 動作確認が完了したら、developブランチからmainブランチへのマージリクエストを作成し、承認後にマージします。 その結果、本番環境に修正版アプリがデプロイされ、表示内容が更新されていることを確認できます。 $ oc describe pod -n devsecops-production nginx-deployment-59ddc6dbb6-lhd6b | grep "Image:"     Image:          registry.gitlab.local.example.com/devsecops-user/devsecops-build-project/nginx:prod-v1.1 この時点で、 Code → Operate の2週目(v1.1)が完了 です。 Gatekeeperによる不正リソースの検知・拒否 ここからは、DevSecOpsライフサイクルのSecに対応します。 最後に、あえて不正な設定を持つリソースをNamespaceにデプロイしてみます。 Gatekeeperのポリシー設定で、 envラベルの値がデプロイ先のnamespace名と一致していないとPodの作成を許可しない 制約 を設定しています。 以下のように、 デプロイ用プロジェクト でdeploymentのlabelsでenvラベルを不正な値に書き換える修正を行い、developブランチにマージします。 このときGatekeeperのポリシーが働き、不正なリソースの作成は拒否されます。 実際のログやイベントを確認すると、Constraint によって違反が検出され、Podのデプロイが失敗していることが分かります。   一番下のReplicaSetはDesired 1に対して、Currentが0であり、Podがデプロイされていないことがわかります。 $ oc get replicasets.apps -n devsecops-develop  NAME                          DESIRED   CURRENT   READY   AGE nginx-deployment-54d94596b6   1         1         1       20m nginx-deployment-5d75b659c5   0         0         0       14h nginx-deployment-6bfd599796   1         0         0       3m48s PodがデプロイされていないReplicaSetのイベントを確認すると、Gatekeeperの 制約テンプレート で設定したエラーメッセージが表示されていることがわかります。 $ oc describe replicasets.apps -n devsecops-develop nginx-deployment-6bfd599796 Events:   Type     Reason        Age                 From                   Message   ----     ------        ----                ----                   -------   Warning  FailedCreate  4m13s               replicaset-controller  Error creating: admission webhook "validation.gatekeeper.sh" denied the request: [require-env-label-match-namespace] Pod 'nginx-deployment-6bfd599796-z7hgf' の 'env' ラベルの値は、Namespace名 'devsecops-develop' と一致する必要があります。現在の値は 'dummy-env' です。 このように、 開発者が意識しなくてもポリシー違反が自動的にブロックされる ことで、セキュリティを犠牲にせずに CI/CD のスピードを維持できることを体験できます。 まとめ 本記事では、GitLab、OpenShift、Gatekeeperを組み合わせて閉域環境にDevSecOpsモデルケースを構築し、デモアプリを用いて以下の流れを確認しました。 GitLab CI/CDによるアプリケーションデプロイの自動化   コード変更からの継続的デリバリー   Gatekeeperポリシーによるセキュリティ担保   このデモを通じて、次のポイントを押さえることができました。 DevOpsだけでは不十分 開発サイクルが迅速化しても、不正なリソースや設定が混入すれば安全性は損なわれる。 ポリシー制御の仕組みが重要 Gatekeeperを用いることで、開発の初期段階から不正なリソースを自動的に排除できる。 GitLabとOpenShiftの統合は実用的 インターネット非接続の閉域環境でも再現可能であり、金融・公共分野を含む実案件にも応用できる。 さらに実環境での利用を考えるなら、コンテナイメージのセキュリティスキャンや、より複雑なポリシー制御を組み合わせることで、より強固なDevSecOpsを実現できます。   まずは小規模なモデルケースから試し、徐々に自社の環境や要件に合わせて拡張していくことをおすすめします。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post DevSecOps実践ガイド:セキュアなCI/CD運用の実践編 first appeared on SIOS Tech. Lab .
アバター
はじめに 前回までに、GitLabとOpenShift、Gatekeeperを閉域環境で構築する手順を紹介しました。 本記事では、その環境を基盤としてGitLabのプロジェクト作成や設定を追加し、CI/CDパイプラインとポリシー検証を組み合わせたDevSecOpsの実践例に向けた環境構築を行います。 特に、金融や公共分野のように高いセキュリティ要件が求められるシステムでは、インターネット非接続環境での開発・運用が前提となるケースが多くあります。本記事で取り上げる構成は、そうした制約下でも有効な実践例となります。 なお、本記事では構築の全手順を網羅するのではなく、モデルケースの全体像と主要な構成要素を中心に解説します。詳細な設定値やコードについては、 こちらのリポジトリ をご参照ください。 ゴール GitLabにビルド用・デプロイ用プロジェクトを作成する OpenShiftのNamespaceや権限を設定する Gatekeeperのポリシーを適用し、CI/CDパイプライン実行時にポリシー違反を検知できるようにする 次回のデモ実演に向けた基盤を完成させる DevSecOpsとは? DevSecOpsとは、DevOpsの迅速な開発・運用プロセスにセキュリティを統合することで、スピードと安全性を両立する手法です。 従来の「開発の後にセキュリティチェックを行う」アプローチではなく、開発ライフサイクルの各段階にセキュリティを組み込む点が特徴です。 詳細については以下の記事で解説していますので、ご参照ください。 DevSecOpsとは?安全性とスピードを両立する開発手法 | SIOS Tech. Lab 前提条件 以下の記事の手順に従って、環境構築が完了していること GitLabとコンテナプラットフォームの連携 | SIOS Tech. Lab OPA/Gatekeeperで始める安心OpenShift運用:構築編 デモアプリの仕様 ベースイメージ:nginx サービス提供ポート:8080 到達性:内部ネットワークのみアクセス可能(外部公開なし) デプロイ方式:Helm(Chart・valuesでイメージタグを切り替え) サンプル構成の全体像 プロジェクトの分割方針 devsecops-build-project(ビルド用) ソースコードとDockerfileを管理し、イメージをビルドしてGitLab Container Registryにpushします。 devsecops-deploy-project(デプロイ用) Helmチャートと環境別のvaluesファイルを管理し、Registryのイメージを参照してOpenShiftにデプロイします。 このように ビルドとデプロイを分けることで、開発コードの管理とデプロイ設定の管理を明確に切り分けられるようにしています。 リポジトリ構成(概要) ビルド用リポジトリ Containerfileとsrc/ : Nginxベースのアプリ .gitlab-ci.yml : イメージビルド&レジストリへpush デプロイ用リポジトリ devsecops-nginx-chart/ : Helmチャート develop-values.yamlとproduct-values.yaml : 環境別設定 .gitlab-ci.yml : Helmを使ったOpenShiftへのアプリのデプロイ ※詳細なディレクトリとファイル内容は こちらのリポジトリ をご覧ください。 ブランチ戦略 feature/* : 開発作業用ブランチ develop : 開発環境に対応 main : 本番環境に対応 feature → develop → main の流れでレビューを経たマージを行い、保護ブランチ設定によりdevelopやmainブランチへの直接pushは禁止しています。 パイプラインの流れ ビルドパイプライン(build-project) ソースコード変更を検知 Runnerがイメージをビルドし、レジストリにpush デプロイパイプライン(deploy-project) Helm設定変更を検知 Runnerがレジストリのイメージをpullし、OpenShiftにデプロイ Gatekeeperがポリシーを検証し、違反があればリソース作成を拒否 構築手順(概要) 手順の流れ 今回のサンプルケースでは以下の構成要素を準備します。 GitLabユーザー作成 ソースコード用プロジェクトの作成 デプロイ用プロジェクトの作成 OpenShift側のNamespaceと権限設定 Gatekeeperのポリシー設定 1. GitLabユーザー作成 管理者アカウントでGitLabにログインし、プロジェクト管理用ユーザーを作成します。 今回使用するプロジェクトのネームスペースはここで作成したユーザー名を指定します。 続いて、作成したプロジェクト管理用ユーザー(devsecops-user)にSSHキーを登録し、Gitでのアクセスを確認します。 作成したプロジェクト管理用ユーザーでログインし、サイドメニューからアバターアイコンを選択→[プロファイルを編集]をクリックして、ユーザー設定画面に移動します。 ユーザー設定画面のサイドメニューで[SSHキー]を選択し、このユーザー用に作成した公開鍵を登録します。 例:SSHキー生成とGitLab接続確認 $ ssh-keygen -t rsa -b 4096 -C "devsecops-user@gitlab.local" $ ssh -T git@gitlab-private.example.local 2. ソースコード用プロジェクト 先ほど作成したプロジェクト管理用ユーザーでログインし、GitLabで新規プロジェクトを作成します。 このプロジェクトはイメージのビルドとレジストリへのイメージ保存を担当します。 プロジェクト作成の詳細な手順は弊社ブログ記事 Git & GitLab 入門 (7) ~Git マスターへの道~「GitLabのプロジェクトについて」 | SIOS Tech. Lab をご参照ください。 続いて、作成したビルド用プロジェクト内でmain と develop ブランチを用いし、保護ブランチの設定を行います。 ブランチの保護設定を行うことで、mainブランチ及びdevelopブランチへの直接pushを防止し、パイプラインの誤動作を防止します。 ブランチ保護設定手順の詳細につきましても、弊社ブログ記事 Git & GitLab 入門 (7) ~Git マスターへの道~「GitLabのプロジェクトについて」 | SIOS Tech. Lab に記載しておりますので、ご参考になれば幸いです。 任意の開発者用ユーザーを作成し、プロジェクトにDeveloper権限で追加します。このユーザーはプロジェクト内でコードをコミットしたり、パイプラインを操作するために利用します。 プロジェクトにユーザーを招待する方法や主要なユーザー権限につきましては、 Git & GitLab 入門 (7) ~Git マスターへの道~「GitLabのプロジェクトについて」 | SIOS Tech. Lab に記載しておりますのでご参照ください。 プロジェクトに追加した開発用ユーザーでログインし、サンプルのアプリコードをリポジトリのfeatureブランチにpushし、管理を開始します。 アプリのベースイメージ(nginx:latestなど)をGitLab Container Registryにpushします。 ※この記事では、OpenShiftの環境を使用しているため、コンテナ管理ツールとしてPodmanを利用しています。Dockerを利用している環境ではpodman→dockerに読み替えてください。 $ podman login registry.gitlab.local.example.com $ podman pull nginx:latest $ podman tag nginx:latest registry.gitlab.local.example.com/devsecops-user/devsecops-build-project/nginx:latest $ podman push registry.gitlab.local.example.com/devsecops-user/devsecops-build-project/nginx:latest 参考: Git & GitLab 入門 (7) ~Git マスターへの道~「GitLabのプロジェクトについて」 | SIOS Tech. Lab 3. デプロイ用プロジェクト プロジェクト管理用ユーザーでGitLabにログインし、今度はデプロイ用のGitLabプロジェクトを新規作成します。 このプロジェクトはレジストリのイメージを参照し、Helmを用いてOpenShiftにデプロイする役割を担います。 ビルド用プロジェクトを作成した時と同様に、mainとdevelopブランチに保護設定を行います。 今回はデプロイ手段としてHelmチャートを利用するため、このプロジェクトのレジストリにHelmが利用可能なコンテナイメージを格納します。 ※この記事では、OpenShiftの環境を使用しているため、コンテナ管理ツールとしてPodmanを利用しています。Dockerを利用している環境ではpodman→dockerに読み替えてください。 $ podman login registry.gitlab.local.example.com $ podman pull docker.io/alpine/helm:3 $ podman tag docker.io/alpine/helm:3 \   registry.gitlab.local.example.com/root/test-project/helm:3 $ podman push registry.gitlab.local.example.com/root/test-project/helm:3 デプロイ用プロジェクトのレジストリにHelmイメージを格納しておくと、パイプライン内で実行されるジョブPodのイメージを指定できます。この指定は、パイプライン定義ファイル(.gitlab-ci.yml)のimageプロパティで行います。 .default_deploy: &default_deploy   stage: deploy   image: registry.gitlab.local.example.com/devsecops-user/devsecops-deploy-project/helm:3   before_script:     - set -euo pipefail     - helm version     - |       if [ -n "${K8S_NAMESPACE:-}" ]; then         HELM_NS_ARG="-n ${K8S_NAMESPACE}"       else         echo "K8S_NAMESPACE variable not provided. Helm will use the current context's namespace."         HELM_NS_ARG=""       fi     - helm dependency update "$HELM_CHART_DIR" || true 今回使用するデプロイ用パイプラインは、ブランチに応じてデプロイ先のネームスペースを決定します。 たとえば、developブランチにマージした時はdevsecops-developネームスペースにアプリをデプロイし、mainブランチにマージした時はdevsecops-productionネームスペースにアプリをデプロイするなどの制御を行います。 deploy_develop:   <<: *default_deploy   tags:     - devsecops-runner   variables:     <<: *common_vars     VALUES_ENV: "deploy/Config/develop-values.yaml"     K8S_NAMESPACE: "$DEPLOY_PROJECT_NAME_DEVELOP"   rules:     - if: '$CI_COMMIT_BRANCH == "develop" && $CI_PIPELINE_SOURCE == "push"'   environment: { name: develop, deployment_tier: development }   script:     - |       set -euo pipefail       : "${HELM_RELEASE:=devsecops-nginx}"       : "${HELM_CHART_DIR:=deploy/devsecops-nginx-chart}"       : "${VALUES_COMMON:=deploy/devsecops-nginx-chart/values.yaml}"       : "${VALUES_ENV:?VALUES_ENV must be set}"       test -f "${HELM_CHART_DIR}/Chart.yaml" || { echo "Chart.yaml not found under ${HELM_CHART_DIR}"; exit 1; }       echo "[RUN] helm upgrade --install ${HELM_RELEASE} ${HELM_CHART_DIR} ${HELM_NS_ARG} -f ${VALUES_COMMON} -f ${VALUES_ENV}"       helm upgrade --install "${HELM_RELEASE}" "${HELM_CHART_DIR}" ${HELM_NS_ARG} -f "${VALUES_COMMON}" -f "${VALUES_ENV}" deploy_production:   <<: *default_deploy   tags:     - devsecops-runner   variables:     <<: *common_vars     VALUES_ENV: "deploy/Config/product-values.yaml"     K8S_NAMESPACE: "$DEPLOY_PROJECT_NAME_PRODUCTION"   rules:     - if: '$CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "push"'       allow_failure: false   environment: { name: production, deployment_tier: production }   script:     - |       set -euo pipefail       : "${HELM_RELEASE:=devsecops-nginx}"       : "${HELM_CHART_DIR:=deploy/devsecops-nginx-chart}"       : "${VALUES_COMMON:=deploy/devsecops-nginx-chart/values.yaml}"       : "${VALUES_ENV:?VALUES_ENV must be set}"       test -f "${HELM_CHART_DIR}/Chart.yaml" || { echo "Chart.yaml not found under ${HELM_CHART_DIR}"; exit 1; }       echo "[RUN] helm upgrade --install ${HELM_RELEASE} ${HELM_CHART_DIR} ${HELM_NS_ARG} -f ${VALUES_COMMON} -f ${VALUES_ENV}"       helm upgrade --install "${HELM_RELEASE}" "${HELM_CHART_DIR}" ${HELM_NS_ARG} -f "${VALUES_COMMON}" -f "${VALUES_ENV}" デプロイ用パイプラインが読み取れるCI/CD変数を登録します。 プロジェクト画面のサイドメニューから[設定] > [CI/CD]を選択し、[変数]のメニューを展開します。 [変数を追加]をクリックすると、CI/CDパイプラインが利用可能な環境変数を定義することができます。今回の例では、環境別のネームスペース名であるDEPLOY_PROJECT_NAME_DEVELOPとDEPLOY_PROJECT_NAME_PRODUCTIONを定義しています。他にも外部サービスのAPIキーなどを登録するなどの利用が可能です。 上記の作業が完了した後、デプロイ用のHelmチャートやマニフェストをfeatureブランチにpushします。 4. OpenShift設定 開発用 (develop) と本番用 (production) のNamespaceを作成し、ラベルを付与します。 ※tagのenvにはdevやprodなどデプロイ先の環境名を指定しています。 $ oc create namespace <namespace> $ oc label namespace <namespace> tag=<env> GitLab Runner用のServiceAccountを作成し、必要なRBAC権限とSCCを付与します。 開発用 (develop) と本番用 (production) のNamespaceのGitLab Runner用のServiceAccountに必要なRBAC権限を付与 GitLab Container RegistryへのPull SecretをNamespaceに登録します。 自己署名証明書を利用している場合はCA証明書をSecretとして登録します。 開発用 (develop) と本番用 (production) のNamespaceのdefault ServiceAccountにanyuidのSCCを付与します。 GitLab Runner用のNamespaceのServiceAccountにデプロイ先namespaceでのedit権限を付与します。 5. Gatekeeper設定 必要なConstraintTemplateを作成します(例:イメージタグに特定文字列を含める、Namespaceとラベルが一致していることなど)。 今回作成したポリシールールは こちらのリポジトリ をご参照ください。 開発環境、本番環境それぞれを対象としたConstraintsを作成します。 oc get コマンドでConstraintTemplateとConstraintsが正しく反映されていることを確認します。 参考: OPA/Gatekeeperで始める安心OpenShift運用:設定編 まとめ ここまでで、GitLabのビルド・デプロイ用プロジェクト、OpenShiftのNamespace設定、Gatekeeperのポリシー適用といった要素が揃い、セキュリティを組み込んだCI/CD基盤のモデルケースが完成しました。これにより、ソースコードの変更がパイプラインを通じて自動的にビルド・デプロイされるだけでなく、Gatekeeperによるポリシー検証によって不適切なリソースの作成を未然に防ぐことが可能になります。 本記事で紹介した構成は、高いセキュリティ要件が求められるシステムにおいても有効なアプローチです。次回の記事では、この環境を活用して実際のパイプライン実行からポリシー違反検知までの一連の流れをデモンストレーションします。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post DevSecOps実践ガイド:CI/CD環境の構築編 first appeared on SIOS Tech. Lab .
アバター
はじめに 前回 までは、GitとGitLabの具体的な機能や操作方法を入門者向けに解説してきました。 今回は、GitLabの根幹となる「DevSecOps」という考え方を中心に解説します。近年のソフトウェア開発では、開発のスピードを上げつつ、セキュリティを確保することが不可欠です。この相反する課題を解決するために必要なアプローチが「DevSecOps」です。 このDevSecOpsをGitLabがどのように実現しているのか、そしてそれがどのようなメリットを生み出すのかを、公式事例を交えて具体的に解説します。 DevOpsとは? まず、DevSecOpsを理解するために、その土台となるDevOpsについて解説します。 DevOpsは、開発チーム(Development)と運用チーム(Operations)が連携し、アプリケーションのビルドからテスト、デプロイ、リリースまでのプロセスを自動化し、高速化する取り組みです。これにより、新しい機能を素早く提供し、顧客のフィードバックに迅速に対応することが可能になります。 DevSecOpsとは? DevSecOpsとは、DevOpsの迅速な開発・運用プロセスにセキュリティを統合することで、スピードと安全性を両立する手法です。 従来の「開発の後にセキュリティチェックを行う」アプローチではなく、開発ライフサイクルの各段階にセキュリティを組み込む点が特徴です。 開発の最終段階で脆弱性が発見されると、その修正には時間とコストがかかり、リリースの遅延につながります。DevSecOpsは、このような手戻りをなくすために、早い段階で問題を検知し、小さな修正で済ませることを目指します。これにより、開発のスピードを保ちつつ、コスト削減と安全性の向上を同時に実現できます。 詳細については以下の記事で解説していますので、ご参照ください。 DevSecOpsとは?安全性とスピードを両立する開発手法 | SIOS Tech. Lab GitLabでのDevSecOpsの扱い GitLabは、DevOpsの統合プラットフォームであるため、DevSecOpsを体現したツールです。 GitLabはCI/CDパイプラインにセキュリティスキャン機能を組み込むことが可能です。開発者は、追加のツールや設定をすることなく、以下の代表的なセキュリティ機能をCI/CDパイプラインに含めることができます。 静的アプリケーションセキュリティテスト(SAST):コードをビルドする前に、ソースコードに存在する脆弱性を自動で検知します。 認証情報検知(Secret Detection):コード内に誤ってコミットされたAPIキーやパスワードなどの機密情報を自動で検出します。 依存関係スキャン(Dependency Scanning):プロジェクトが使用しているライブラリやフレームワークに既知の脆弱性がないかをチェックします。 これらのスキャン結果は、マージリクエスト画面にCI/CDパイプラインの実行結果として直接表示されるため、レビュー時にコード品質とセキュリティの両方を一度に確認できます。 参考: Git & GitLab 入門 (6) ~Git マスターへの道~「GitLabの画面説明とよく利用される機能説明」 GitLab公式で提示しているDevSecOpsの事例について GitLabのDevSecOps機能は、規模を問わず多くの企業で成果を上げています。ここでは、GitLabの公式事例からそのメリットを具体的に見てみましょう。 参考: https://about.gitlab.com/ja-jp/customers/ エンタープライズ事例:Hilti社(デプロイ時間の短縮) 建設業界の大手であるHiltiは、以前、ソフトウェア開発の一部を外部に委託しており、社内でのコード管理やCI/CD体制が十分に整っていませんでした。そのため、バグや脆弱性への対応が後手に回り、セキュリティ上のリスクやコード品質の低下が課題となっていました。 これらの課題を解決し、セキュリティスキャンを最優先にソフトウェア開発を社内化するため、統合のしやすさ、SCM (Source Code Management)、豊富なSAST/DAST等のセキュリティ機能を理由にGitLab Ultimateを採用しました。 GitLab導入の具体的な成果として、デプロイ時間が平均3時間からわずか15分に短縮されました。これは、以下が大きな要因です。 開発・テストチームがコードを管理し、脆弱性を事前に発見できるようになった フィードバックループが6日から3日に短縮されたこと コードチェック頻度が3か月6回から週2回に増加 これにより、Hiltiはセキュリティ、コード品質、開発効率、チームコラボレーションを大幅に向上させることができました。 参考: https://about.gitlab.com/customers/hilti/ ミッドマーケット事例:Carfax社(脆弱性の早期発見) 自動車履歴データベースを提供するCarfaxは、以前、複数のDevOpsツールチェーンの維持管理をするため、多くの時間やコストがかかっていました。さらに、開発ライフサイクル後半の手動による脆弱性スキャンで問題が発覚することが多く、迅速な修正が難しい状況でした。 より早い段階でセキュリティリスクを検知したいという課題から、GitLabのDevSecOpsプラットフォームを採用しました。Carfaxは導入後6ヶ月以内に、コードをGitLabに移し、GitLabのセキュリティスキャンを活用し始めました。 GitLabの自動セキュリティ機能(依存関係スキャン、コンテナスキャン、シークレット検出など)を導入することで、Carfaxは1年間で脆弱性の約3分の1を開発ライフサイクルのかなり早い段階で発見できるようになりました。これにより、開発チーム全体がソフトウェアライフサイクルの最も早い段階からセキュリティを考慮する「シフトレフト」を実現し、問題の修正にかかる時間とコストを大幅に削減し、セキュリティを向上させました。 参考: https://about.gitlab.com/customers/carfax/ 中小企業(SMB)事例:Jasper Solutions社(オールインワンの利点) 政府・民間向けのソフトウェア開発を行うJasper Solutionsは、以前、 複数の個別ツールを組み合わせた開発パイプラインを利用していましたが、個々のツールのバージョンアップが原因でパイプラインが頻繁に機能しなくなり、開発チームは顧客向けのコード開発よりもその修正に多くのリソースを割かなければなりませんでした。 こうした運用負荷を根本から解決するため、GitLabをCI/CD、SCMを統合した「オールインワン」プラットフォームとして採用しました。 GitLabの「オールインワン」プラットフォームにより、パイプラインの破損がほぼなくなり、単一のアップグレードでパイプライン全体が常に最新の状態に保たれるため、開発チームはアプリケーション開発に集中できるようになりました。この統合によって、以下の具体的なメリットが生まれています。 1製品あたり年間平均約350人時の作業時間を削減 個別のツールを維持管理する費用と比較して年間33〜37%のコスト削減 サイクルタイムが30%短縮され、デプロイ頻度が25%向上 Jasper Solutionsは、GitLabの「オールインワン」の利点を最大限に活用することで、複数のツールチェーンの維持管理から解放され、開発への集中と運用コストの削減を同時に実現できました。 参考: https://about.gitlab.com/customers/jasper-solutions/ GitLabのDevSecOpsを導入することによって、Hilti社ではデプロイ時間の短縮、Carfax社では脆弱性の早期発見、Jasper Solutions社では運用コスト削減と安定化が実現されました。 事例 改善効果 Hilti社 デプロイ時間の短縮(平均3時間から15分) Carfax社 脆弱性の早期発見(約3分の1) Jasper Solutions社 運用コスト削減と安定化(年間33〜37%のコスト削減) まとめ 今回は、GitLabがCI/CDパイプラインにセキュリティスキャン機能を統合することで、開発スピードと安全性を両立する「DevSecOps」という手法を実現していることを解説しました。 そして、GitLabが実際の企業事例(Hilti、Carfax、Jasper Solutions)でどのような具体的な成果(デプロイ時間の短縮、脆弱性の早期発見、運用コストの削減など)を生み出しているかを具体的に見てきました。 これまで学んだGitLabの基本操作を踏まえ、次は実際にDevSecOpsを体験できる環境を構築する方法をご紹介します。 参考文献 https://about.gitlab.com/ja-jp/customers/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Git & GitLab 入門 (10) ~Git マスターへの道~「GitLabでDevSecOps」 first appeared on SIOS Tech. Lab .
アバター
/br今号では、nftables について、その仕組みや設定方法について説明します! nftables とは nltables とはパケットフィルタリング (通過するパケットの IPアドレス、プロトコル、ポート番号などをフィルタリング設定に基づいてチェックし、通信を許可・拒否を判断すること) ツールの名称です。カーネル 3.13 (RHEL だとバージョン 8系) から導入されました。 従来は iptables、ip6tables、arptables、ebtables といった複数のツールを使い分けてフィルタリング設定をする必要がありましたが、これらのツールを 1つの nft コマンド に統合し、より管理しやすくなりました。 nftables は従来のツールと比較して構文がシンプルかつ柔軟に設定ができるようになっています。 なお、nftables について過去に下記の記事でもご紹介しています。2019年の記事ということもあり、前回説明しきれなかった部分も含めてご紹介できればと思います。 ※内容が重複してしまう部分もあります。ご了承ください。 https://tech-lab.sios.jp/archives/16930#teburuno_she_ding フィルタリング設定の全体的な構造 nftables では、フィルタリング設定のことを ルールセット と呼びます。 ルールセットは、inet、ip、ip6 などのアドレスファミリごとに作成できる テーブル 、さらにテーブル内にフィルタリングのルールをひとまとめに管理するための チェーン 、そしてチェーン内で具体的なルール設定を行うための ルール が含まれる構造になっています。 基本の書式 nft コマンド の基本的な使用方法をご説明します。 ルールセットの追加 nftables によるフィルタリング設定は、 ①テーブル、②チェーン、③ルール 、という順序で行なっていきます。 テーブルの追加 テーブルを新しく追加するには nft add table コマンド を使用します。 例1:inet ファミリのテーブルを作成 # nft add table inet table1 例2:ip4 ファミリのテーブルを作成 # nft add table ip table2 チェーンの追加 チェーンを新しく追加するには nft add chain コマンド を使用します。 例1:table1 テーブルに新しいチェーンを作成 # nft add chain inet table1 chain1 { type filter hook input priority 0 \; } ※ “{}” 内で指定する type、hook、priority に指定可能な値については、過去にご紹介した記事でも説明しています。 (ブログより抜粋) —– ・type には、filter、route、nat のいずれかを設定します。 ・hook には、prerouting、input、forward、output、postrouting のいずれかを設定します。 ・priority には、チェインの優先度 (整数値) を設定します。  値が小さいほど、優先度は高くなります。また、負の値を設定することもできます。 —– ルールの追加 ルールを新しく追加するには nft add rule コマンド を使用します。 例1:table1 テーブル内の chain1 に、22 番ポート (SSH) による外部アクセスを許可するルールを作成 # nft add rule inet table1 chain1 tcp dport 22 accept 例2:table1 テーブル内の chain1 に,、80 番ポート (HTTP) による外部アクセスを許可するルールを作成 # nft add rule inet table1 chain1 tcp dport 80 accept ルールセットの表示 ルールセットの内容を表示するには nft list ruleset コマンド を使用します。 # nft list ruleset table inet table1 { chain chain1 { type filter hook input priority filter; policy accept; tcp dport 22 accept tcp dport 80 accept } } テーブルの一覧を表示するには nft list tables コマンド を使用します。 ※テーブルの一覧のみ。内容は表示されません # nft list tables table inet table1 特定のチェーンに設定されているルールの内容を表示するには、 nft list chain コマンド を使用します。 # nft list chain inet table1 chain1 table inet table1 { chain chain1 { type filter hook input priority filter; policy accept; tcp dport 22 accept tcp dport 80 accept } } ルールセットの削除 ルールを削除するには nft delete コマンド を使用します。 なお、ルールの削除には各ルールごとに設定されている ハンドル番号 が必須となります。 ハンドル番号の確認方法は、上で説明した nft list chain コマンドに –handle もしくは -a オプションを指定します。 # nft -a list chain inet table1 chain1 table inet table1 { chain chain1 { # handle 1 type filter hook input priority filter; policy accept; tcp dport 22 accept # handle 2 tcp dport 80 accept # handle 3 } } # nft --handle list chain inet table1 chain1 table inet table1 { chain chain1 { # handle 1 type filter hook input priority filter; policy accept; tcp dport 22 accept # handle 2 tcp dport 80 accept # handle 3 } } tcp dport 22 accept の横に handle 2 、 tcp dport 80 accept の横に handle 3 と記載されており、各ルールのハンドル番号を確認することができました。 例えば、上記のうち 22 番ポート (SSH) のルールを削除するには、下記の様に handle 2 と指定します。 # nft delete rule inet table1 chain1 handle 2 次号について 次号では、 nftables の設定例や、知っておくと便利な tips についてご紹介します! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 知っておくとちょっと便利!nftables によるパケットフィルタリング1 first appeared on SIOS Tech. Lab .
アバター
こんにちは! 今月も「OSSのサポートエンジニアが気になった!OSSの最新ニュース」をお届けします。 9/10、IPA (情報処理推進機構) が、「情報セキュリティ白書2025」PDF 版を公開しました。 プレス発表「情報セキュリティ白書2025」PDF版の公開 https://www.ipa.go.jp/pressrelease/2025/press20250910.html 9/16、LPI-Japanは Linux の学習教材の最新版である「Linuxシステム管理標準教科書 バージョン2.0.0」を公開しました。 PDF版と ePub版は無償で提供されています。 LPI-Japan、無償のLinux学習用教材「Linuxシステム管理標準教科書」最新版を公開 https://japan.zdnet.com/article/35238032/ 総務省のサイトより、9/18 に実施された AI セキュリティ分科会の資料が公開されました。 総務省 – AIセキュリティ分科会(第1回) https://www.soumu.go.jp/main_sosiki/kenkyu/cybersecurity_taskforce/02cyber01_04000001_00321.html ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【2025年9月】OSSサポートエンジニアが気になった!OSS最新ニュース first appeared on SIOS Tech. Lab .
アバター
はじめに これまで本ブログでは、GitLabをDevSecOpsのための開発プラットフォームとして利用する際に必要となる主要機能(コンテナレジストリやCI/CD)について紹介してきました。今回はその基盤をより安定して運用するために欠かせない冗長化構成について紹介します。 概要 GitLabを構成するコンポーネントとして以下のものがあります: GitLab Rails UIの提供やAPIの管理を行うGitLabの中核を成すウェブアプリケーションです Consul GitLabの各コンポーネントのサービスディスカバリーとヘルスチェックを行うコンポーネントです Database(PostgreSQL) GitLabの主要データ(プロジェクト、ユーザーなど)を保存するデータベースです Sidekiq GitLabのバックグラウンドジョブを非同期で処理するためのコンポーネントです Redis GitLabの一時的なデータ(キャッシュ、ジョブキューなど)を保存する高速なインメモリデータストアです Gitaly Cluster Gitリポジトリの読み書きを行うコンポーネントです 今回は以下のようなGitLabの構成例( 例:最大 1000 RPS または 50,000 ユーザー )を参考にして各コンポーネントの冗長化について説明します。 GitLabの構成例(引用: 最大 1000 RPS または 50,000 ユーザー ) 各コンポーネントの冗長化 GitLab Rails GitLab Railsの冗長化 GitLab RailsはGitLabのアプリケーションサーバーです。想定されるアクセスユーザーに合わせてノードを水平スケールする必要があります。(参考: https://docs.gitlab.com/administration/reference_architectures/ ) アプリケーションサーバーは多数のユーザーからのリクエストを処理する必要があります。また、アプリケーションサーバーから内部の各種コンポーネントに多数のリクエストが送られます。そのため、GitLab Railsの冗長化には外部ロードバランサーと内部ロードバランサーが使われます。 外部ロードバランサーはGitLabへアクセスする際の外部からのSSH、HTTPS通信のトラフィックを分散させます。TLS終端をロードバランサーによって行うことが可能です。 内部ロードバランサーはPgBouncerやGitaly Cluster (Praefect)への接続などの内部コンポーネント同士の通信を仲介して、負荷を分散します。 Consul Consulの冗長化 Consulは各コンポーネントの監視を行い、サービスディスカバリーとヘルスチェックを行うコンポーネントです。GitLabの各コンポーネント同士の接続の手伝いをします。 クォーラム(クラスターが正常に機能する最小台数)を維持するために、3ノード以上の奇数ノードにConsulをデプロイする必要があります。 Database(PostgreSQL) Database(PostgreSQL)の冗長化 GitLabでは主要データ(プロジェクト、ユーザーなど)を保存するデータベースとしてPostgreSQLが利用されます。 GitLabのPostgreSQLでは単一障害点を回避するためにプライマリDBとセカンダリDBの2種類が用意されます。プライマリDBは実際に利用されるメインのDBで、セカンダリDBはプライマリの内容をリアルタイムで複製している読み取り専用の予備のDBです。 PgBouncerは各コンポーネントがPostgreSQLのDBに接続を行う際に仲介をして、DB本体への負荷を軽減させるコンポーネントです。PgBouncerがないとGitLabへの接続制限によって、エラーが出たり処理速度が低下します。PgBouncer自身は内部ロードバランサーによって負荷分散されます。 また、PatroniというPostgreSQLのHAクラスタを管理するツールを用いることによってプライマリDBに障害が起きた場合、セカンダリDBをプライマリに昇格する処理が自動的に行われます。 Sidekiq Sidekiqの冗長化 SidekiqはGitLabの様々なバックグラウンドジョブ(メール送信、CIジョブなど)を処理するコンポーネントです。 Sidekiqのキューにジョブが追加されていくと、あるコンポーネントで処理が低下した場合、連鎖的にすべてのジョブの速度が低下する可能性があります。そのような場合の対策として、以下のようなものがあります。 複数インスタンスを立ち上げて処理能力を増やす ジョブを小さな単位に分割する ジョブのキューを最適化する 上記に示す通りSidekiqの冗長化は単純に水平スケールするだけでなく、ジョブキューの設計を適切に行うことが重要になります。 Sidekiqはログを見ることによってジョブの実行時間や実行回数を視覚的に確認することが可能です。その結果をSidekiqのキューの設計に反映させて、継続的にキューの最適化を行う必要があります。 Sidekiqのログ(引用: GitLabの負荷分散 ) Redis Redisの冗長化 RedisはGitLabで高速処理が求められる様々な一時的なデータを保存するために利用されます。PostgreSQLと同じくプライマリとセカンダリに別れていますが、Redisのセカンダリは読み取りができません。 ジョブキューやユーザーセッションの状態の情報など、失われるとGitLabの機能が停止するような情報はRedis Persisetentに保存され、Cacheやログなどの失われてもGitLabが動作できるような情報はRedis Cacheに保存されます。 Redis Sentinelというコンポーネントによって、Redisのプライマリで障害が起きた場合、セカンダリに自動的に切り替えが行われます。 Redisクラスターはクォーラム(クラスターが正常に機能する最小台数)を維持するために、3ノード以上の奇数ノードにデプロイする必要があります。 Gitaly Cluster Gitaly Clusterの冗長化 GitalyはGitリポジトリの読み書きを行うコンポーネントです。 Gitaly ClusterはすべてのGitリポジトリがすべてのGitalyノードに保存され、そのうち一つがプライマリとして動作します。 Gitalyへの接続はすべてPraefectというGitaly Clusterのリクエストをルーティングするコンポーネントを経由します。これによってGitalyノードで障害が起きた場合、自動的にフェイルオーバーします。また、PraefectはTLSの接続をサポートしています。 Praefect自身は内部ロードバランサーによって負荷分散されます。また、クォーラム(クラスターが正常に機能する最小台数)を維持するために、3ノード以上の奇数ノードにデプロイする必要があります。 PraefectにはGitaly Clusterのステータスを保存する独自のDB(Praefect PostgreSQL)が必要になります。GitLabのLinuxパッケージで構築する場合、非HA構成のDBになります。高可用性を保ちたい場合は外部の冗長化されたPostgreSQLが必要になります。 終わりに 今回はGitLabの各コンポーネントの冗長化について解説しました。セキュアで継続的な開発環境を実現するための土台として、冗長化の考え方を理解しておくことはDevSecOpsの観点でも重要です。今回示した例は1000RPSまたは50,000ユーザーを想定した大規模な環境です。各々のユースケースに適したGitLabの構成を設計し、その環境規模に応じてどのコンポーネントを冗長化するべきか判断する必要があります。今回の記事がその判断材料の助力になれば幸いです。 参考 GitLabコンポーネントリスト https://docs.gitlab.com/development/architecture/#component-list GitLabリファレンスアーキテクチャ https://docs.gitlab.com/administration/reference_architectures/ 例:最大 1000 RPS または 50,000 ユーザー https://docs.gitlab.com/administration/reference_architectures/50k_users/ マルチノードGitLab向けロードバランサー https://docs.gitlab.com/administration/load_balancer/ GitLabの負荷分散 https://docs.gitlab.com/development/scalability データベース負荷分散 https://docs.gitlab.com/administration/postgresql/database_load_balancing/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post GitLabの冗長化構成を徹底解説:安定運用のための実践ガイド first appeared on SIOS Tech. Lab .
アバター
はじめに 前回の記事では、2回にわたりGitLab CI/CDの基本的なパイプライン作成方法 を解説しました。ジョブの定義からステージの構成まで、一通りの流れを実際に試しながら理解できたと思います。 しかし、実際にチーム開発を進めていくと、パイプラインの定義ファイルである.gitlab-ci.ymlがすぐに肥大化しがちです。 同じ処理を複数のジョブに書いてしまう プロジェクトごとに似たような CI 定義をコピペして使い回す こうした状態になると、修正や共通化が難しくなり、運用コストが増えてしまいます。 そこで今回の記事では、GitLab CI/CDが用意している include と extends の仕組みに注目します。これらを活用することで、設定を整理し、再利用しやすい形に整えることができます。 小さな検証を通して、それぞれの機能がどのように役立つかを紹介していきます。 include機能:外部ファイルのインポート includeは、別ファイルに書かれたCI定義を取り込む機能です。別のプロジェクトにあるファイルを読み込めるのが大きな特徴です。今回の検証では、テスト用にGitLab上で 2 つのプロジェクトを用意し、一方のプロジェクトにあるパイプライン定義を、もう一方のプロジェクトからincludeで読み込む形を確認しました。 検証環境 メインプロジェクト:runner-test-project-1 .gitlab-ci.yml(実際にパイプラインを実行する定義ファイル) インポート用プロジェクト:runner-test-project-2 ci/shared.yml(他のプロジェクトから取り込んで使うためのジョブ定義ファイル) 設定例(実行側) # runner-test-project-1/.gitlab-ci.yml variables:   FROM_PROJECT: "overridden-in-runner-test-project-1" include:   - project: "group/runner-test-project-2"     ref: "main"     file: "/ci/shared.yml" stages: [test] check-local:   stage: test   script:     - echo "FROM_PROJECT=${FROM_PROJECT}" 設定例(includeされる側) # runner-test-project-2/ci/shared.yml project-job:   stage: test   variables:     FROM_PROJECT: "default-in-provider-project"   script:     - echo "FROM_PROJECT=${FROM_PROJECT}" 実行結果 check-local(ローカルジョブ)と project-job(外部ジョブ)がどちらもパイプラインに表示される すべてのジョブが成功 FROM_PROJECT=overridden-in-runner-test-project-1 が出力され、実行側の変数が優先されることを確認 ポイント 変数の上書き :同じ名前の変数が複数定義されている場合、最終的にはメインの.gitlab-ci.ymlファイルで定義された値が優先されます。外部ファイル側はデフォルト値を置き、環境依存の値はメイン側で上書きするのがベストです。 権限 :実行するユーザーが参照先リポジトリを読む権限を持っている必要があります。安定運用のためには、参照元・参照先を同じグループ内にまとめておくとよいでしょう。 ref の固定 :main を参照すると、外部ファイルの変更が即座に反映されてしまうため、安定性を重視するなら、タグやリリースブランチを指定するのがおすすめです。 参考: Use CI/CD configuration from other files | GitLab Docs extends機能:共通設定の継承 extendsは、ジョブごとに共通する設定をテンプレートとしてまとめ、そこから継承できる仕組みです。同じ処理や変数を繰り返し記述せずに済むのが大きな特徴です。今回の検証では、共通設定を.default-templateとして定義し、job_aではそのまま継承、job_bでは一部の変数を上書きする形を確認しました。 検証環境 任意のプロジェクトに extends-gitlab-ci.yaml を作成し、次の内容を記述しました。 設定例 stages: [test] # 共通設定(テンプレート) .default-template:   stage: test   image: registry.gitlab.local.example.com/root/registry-project/alpine:latest   tags:     - devsecops-runner   before_script:     - echo "BEFORE(from base) run common setup"   variables:     BASE_VAR: from-base     OVERRIDE_ME: from-base # 継承のみ(上書きなし) job_a:   extends: .default-template   script:     - echo "A BASE_VAR=$BASE_VAR OVERRIDE_ME=$OVERRIDE_ME"     - echo "A IMAGE=$(cat /etc/alpine-release 2>/dev/null || echo unknown)" # 一部上書き(variables を上書き) job_b:   extends: .default-template   variables:     OVERRIDE_ME: from-job-b   script:     - echo "B BASE_VAR=$BASE_VAR OVERRIDE_ME=$OVERRIDE_ME" 実行結果 すべてのジョブが成功 job_a BASE_VAR=from-base OVERRIDE_ME=from-base before_script の “BEFORE(from base) run common setup” が実行され、image も alpine:latest が利用されている job_b → 変数 OVERRIDE_ME はジョブ側の値で上書き、BASE_VAR や before_script はテンプレートの値がそのまま反映されている BASE_VAR=from-base(テンプレートのまま) OVERRIDE_ME=from-job-b(ジョブ側の値で上書き) before_script と image はテンプレートの設定が適用されている ポイント 共通化のメリット :before_script や変数をテンプレートにまとめることで、修正が必要になった際に1箇所を直すだけで全ジョブに反映できます。結果として、ジョブテンプレートの管理や保守がシンプルになり、影響範囲も明確に把握できます。 変数の上書き :テンプレートとジョブの両方に同じキーが定義されている場合、ジョブで定義された値が優先されます。テンプレートは共通の値を設定し、必要に応じてジョブ側で上書きするのが基本的な使い方です。 参考: Optimize GitLab CI/CD configuration files まとめ includeを使うと、外部ファイルを取り込んで 共通ジョブを複数のプロジェクトで再利用できます。 extendsを使うと、共通設定をテンプレート化してジョブごとの差分だけを簡潔に記述できます。 どちらの機能も、複雑化しやすい .gitlab-ci.yml を整理し、変更や保守を効率化するために欠かせない仕組みです。 チームやプロジェクトが大きくなるほど、パイプラインの管理は難しくなります。include とextendsを活用すれば、CI/CD 設定をシンプルかつ再利用性の高い形に整え、大規模な開発環境でも安定して運用できる基盤を作ることができます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post GitLab CI/CD 実践[応用編]:共通設定と外部ファイルの利用 first appeared on SIOS Tech. Lab .
アバター
本書は、2025年8月に公開した マイクロサービス化の課題とその解決策 に関するホワイトペーパーを紹介するものです。 「ビジネスの変化に柔軟かつスピーディーに対応するためのマイクロサービス化だったはずが、なぜか開発は遅くなり、運用は複雑怪奇、分散モノリスのようになってしまった…」 もし、読者の皆様が企業の技術リーダーやアーキテクトとして、少しでも心当たりのあるのであれば、本書をお勧めいたします。さらに、AI時代のマイクロサービス化においては、別の問題も待ち構えていることを意識する必要があります。 AIが生み出すマイクロサービス化の新しい課題 ご存知の通り、生成AIは、驚異的なスピードでコードを生成します。しかし、一方ではビジネスの意図を汲み取ることが苦手です。 その結果、AIが高速で生成したコードが、気づかぬうちにサービスをまたがるデータの整合性を破壊し、ビジネスに致命傷をもたらしかねません。ここは人間による介入が必要な部分なのです。従来のSagaパターンのような複雑な手法のみでは、AIが大量に生み出すコードの整合性を人間が検証し続けるには、もはや限界に近づいています。 課題の全体像と解決へのアプローチ この度公開したホワイトペーパー「マイクロサービス化の課題とその解決策」では、マイクロサービス化に関する旧来からの課題に対しては、単なる技術論のみではなく、技術論から一歩離れた組織論から検討する体系的なアプローチでの解決策を提案します。更に、AI時代のマイクロサービス固有の課題であるデータ整合性担保に対する解決策として、強力な選択肢の一つとなり得る ScalarDB を紹介します。 ホワイトペーパーの構成(11ページ) 第1部:問題提起 – なぜマイクロサービス化は失敗するのか 第2部:SIOS APIエコシステムとScalarDBによる包括的解決策 第3部:実践的トレードオフと典型的な設計パターン 第4部:結論   経験豊富なアーキテクトの皆様へ 第3部では、本書の記載に対して経験豊富なアーキテクトであればこそ抱くであろう妥当な疑問に対して、正面から向き合います。 疎結合と「時間的カップリング」の板挟み 2PCの性能オーバーヘッドとTCO(総所有コスト) アプリケーション層からインフラ層への複雑性の移動は問題解決になるか? ストラングラーフィグパターンへの応用   ▼ホワイトペーパーのダウンロードはこちらから https://api-ecosystem.sios.jp/scalar/download/scalarsiosapi01.html ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post マイクロサービス化の新旧課題の解決策を提案するホワイトペーパーの紹介 first appeared on SIOS Tech. Lab .
アバター
はじめに こんにちは!珍しくブログを連投しているなーがです。今回はClaude Code UIをインストールした際につまづいたことについて書こうと思います。 最近、AIを活用した開発ツールが次々と登場していますが、その中でもClaude Code UIは特に注目を集めています。しかし、Windows環境でのインストールには意外な落とし穴があることがわかりました。同じ問題で悩む方のお役に立てればと思い、解決方法をまとめてみました。 時間がない方のために Claude Code UIをWindows環境でインストールする際は、Visual Studio Installerから以下の2つをインストールする必要があります: ワークロード「C++によるデスクトップ開発」 個別のコンポーネント「最新のSpectre 軽減のライブラリ」 これらがないと、 npm install 時にビルドエラーが発生します。 Claude Code UIとは Claude Code UIは、Anthropic社のClaude Code CLIやCursor CLIをWebブラウザ経由で操作できるようにするWebアプリケーションです。これにより、ローカル環境だけでなく、スマートフォンやタブレットなどのモバイルデバイスからもAIを活用したコーディングが可能になります。 主な特徴 ブラウザベースのターミナルインターフェース Claude CodeやCursorの全機能をWeb UIから利用可能 モバイルフレンドリーなレスポンシブデザイン Cloudflare Tunnelなどと組み合わせて、どこからでもアクセス可能 GitHubリポジトリ:https://github.com/siteboon/claudecodeui 関連するいくつかのブログが投稿されています。 スマホでClaude Code!?外出先でClaude Codeを使ってみた!! (こちらは弊社の細川君の記事なのでぜひ読んでください!) 【徹底解説】Claude Code UI と Cloudflare Tunnelでスマホから快適にAIコーディング Claude Code UIレビュー:スマホからでもAIコーディングが可能に!開発効率が劇的向上 インストール手順と遭遇した問題 前提条件の確認 READMEによると、以下の前提条件が必要です: Prerequisites Node.js v20 or higher Claude Code CLI installed and configured, and/or Cursor CLI installed and configured 私のPCにはすでにv20以上のNode.jsとClaude Code CLIがインストール済みだったので、さっそくインストールを開始しました。 インストール開始 まずはリポジトリをCloneします。 git clone https://github.com/siteboon/claudecodeui.git Cloneされたら、ディレクトリを移動します。 cd claudecodeui ライブラリをインストールします。 npm install 最初のエラー:Visual Studio C++ツールセットが見つからない $ npm install npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory... (中略) npm error gyp ERR! find VS - found "Visual Studio C++ core features" npm error gyp ERR! find VS - missing any VC++ toolset npm error gyp ERR! find VS could not find a version of Visual Studio 2017 or newer to use npm error gyp ERR! find VS npm error gyp ERR! find VS ************************************************************** npm error gyp ERR! find VS You need to install the latest version of Visual Studio npm error gyp ERR! find VS including the "Desktop development with C++" workload. npm error gyp ERR! find VS For more information consult the documentation at: npm error gyp ERR! find VS https://github.com/nodejs/node-gyp#on-windows npm error gyp ERR! find VS ************************************************************** すっごく長いエラーが発生して最初は驚きましたが、よく見ると意味は明確でした。 エラーの原因: node-pty というNode.jsのネイティブモジュールのビルドでエラーが発生しています。 node-pty は疑似ターミナル(PTY)を作成するためのモジュールで、Claude Code UIのターミナル機能に必要不可欠です。 Windowsでこのようなネイティブモジュールをビルドするには、C++のコンパイラツールチェーンが必要となります。エラーメッセージは「Visual StudioのC++開発ツールが見つからないので、最新のVisual Studioをインストールして『C++によるデスクトップ開発』ワークロードをインストールしてください」と教えてくれています。 解決策1:Visual Studio C++開発環境のインストール Visual Studio Installerを開きます。Visual Studioをインストールされていない方は、 こちら からダウンロードしてください。 「変更」をクリックします。 「ワークロード」タブで「C++によるデスクトップ開発」を選択してインストールをクリックします。(筆者はインストール済みのため、ボタンが「閉じる」になっています) インストールが終わったら、再度ライブラリをインストールするコマンドを実行します。 npm install 2回目のエラー:Spectre軽減ライブラリが必要 $ npm install npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory... (中略) npm error C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.CppBuild.targets(511,5): error MSB8040: Spectre 軽減のライブラリは、このプロジェクトに必要です。使用されているツールセットとアーキテクチャについては、Visual Studio インストーラー (個々のコンポーネント タブ) からインストールします。詳細情報: https://aka.ms/Ofhn4c 今度は「Spectre 軽減のライブラリ」が必要というエラーが発生しました。 Spectreとは? 2018年に発見されたCPUの脆弱性で、投機的実行という高速化技術の副作用を悪用して、本来アクセスできないメモリ領域の情報を盗み見ることができる攻撃手法です。MicrosoftはこれらのセキュリティリスクからWindowsアプリケーションを保護するため、Visual Studioに特別な軽減ライブラリを提供しています。 最近のプロジェクトでは、セキュリティ上の理由から、これらの軽減ライブラリを使用することがデフォルトで要求されることが多くなっています。 解決策2:Spectre軽減ライブラリのインストール 診断コードMSB8040の解決策は Microsoft公式リファレンス に記載されている通り、Visual Studio Installerの「個別のコンポーネント」タブから最新のSpectre軽減ライブラリを選択してインストールします。 インストールが終わったら、三度目の正直でライブラリをインストールするコマンドを実行します。 npm install インストール成功! $ npm install npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory... (警告は続きますが、これらは依存関係の警告なので問題ありません) added 613 packages, and audited 614 packages in 2m 141 packages are looking for funding run `npm fund` for details 1 low severity vulnerability To address all issues, run: npm audit fix Run `npm audit` for details. やっとライブラリのインストールが成功しました!警告はいくつか表示されていますが、これらは依存パッケージの非推奨に関するものなので、動作には影響しません。 あとは README.md に書いてある通りに実行するだけです! トラブルシューティング もし同様の問題に遭遇した場合は、以下の点を確認してください: 1. Visual Studioのバージョン Visual Studio 2017以降が必要です Community版で問題ありません 2. 必要なコンポーネント 必須 : C++によるデスクトップ開発(ワークロード) 必須 : 最新のSpectre軽減のライブラリ(個別のコンポーネント) 3. Node.jsのバージョン Node.js v20以上が必要です node --version で確認できます 4. 権限の問題 管理者権限でコマンドプロンプトを実行してみてください node_modules フォルダを削除してから再度 npm install を試してください まとめ 今回はClaude Code UIをWindows環境でインストールする際につまづいたことについて書きました。一見すると単純なnpmパッケージのインストールですが、ネイティブモジュールを含む場合は、Visual StudioのC++ビルドツールが必要になることがあります。 特にWindows環境では、以下の2つが必要です: Visual StudioのC++によるデスクトップ開発ワークロード Spectre軽減のライブラリ これらを事前にインストールしておけば、スムーズにセットアップできるはずです。 昨今のAIツールの発展はめまぐるしいものがありますが、こうしたツールを活用することで、開発効率は飛躍的に向上します。インストールで少し苦労するかもしれませんが、その価値は十分にあると思います。 AIツールの進化に負けずに、楽しく開発していきましょう! 参考リンク Claude Code UI GitHub Repository Node.js Visual Studio Downloads MSB8040エラーの解決方法(Microsoft公式) node-gyp on Windows(GitHub) ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Code UIをインストールする際につまづいたこと first appeared on SIOS Tech. Lab .
アバター
はじめに 前回 は、CI/CDの基本から、GitLab Runnerの導入、そしてコンテナイメージのビルド・プッシュ・デプロイまで、一連のワークフローを解説しました。 今回は、マージリクエスト(MR)の重要な役割であるコードレビューに焦点を当てます。コードレビューは、バグの早期発見やコード品質の向上、さらにはチームの知識共有を促す、開発プロセスに欠かせない作業です。 本記事では、GitLabのMR機能を活用し、レビューをスムーズに進めるための具体的な操作方法を、レビュアー(レビューする人)とレビューイ(レビューしてもらう人)の両方の視点から解説します。 コードレビューの概要 コードレビューとは、他の開発者が書いたコードを読み、フィードバックや改善点を議論するプロセスです。これは、単にバグを見つけるだけでなく、チーム全体のコード品質を高め、知識を共有し、開発の一貫性を保つために重要です。 GitLabでは、このコードレビューのプロセスがマージリクエスト(MR)に統合されています。MR上でコードレビューを行う流れは以下のようになります。 レビューイ(レビューしてもらう人):構文チェック後にMRを作成し、パイプラインの自動テストが完了していることを確認する。 レビューイ:レビュアーを指定してレビュー依頼を出す。 レビュアー(レビューする人):レビュー依頼を受けたらMR画面を確認し、MRの概要を把握する。 レビュアー:コードの変更点へのコメントをする レビューイ:MRのレビューを確認し、コードの変更が必要な場合は修正する。 レビュアー:コードの変更点に問題がなければMRを承認する。 レビューイ:MRが承認されたらマージする。 今回はレビューイが承認をもらったら、レビューイ自身でマージする流れで紹介します。 承認に複数名必須な場合もあるので、すべての承認者が承認してからマージするためにレビューイ自身でマージする流れを紹介しましたが、誰がマージするかはチーム文化に依存します。 マージリクエストのレビュー機能紹介 MRの設定 マージリクエスト(MR)を作成する際、タイトルや説明、担当者といった様々な項目を設定できます。 タイトル MRの目的を示します。一目で内容がわかるように「feat: 新機能追加」や「fix: バグ修正」といったルール(コミット規約)を適用するのが一般的です。 説明 以下の点を意識して記載すると、レビュアーは内容を素早く理解できます。 なぜこの変更が必要かといった背景や課題 何を変更したかといった技術的な詳細 何を確認してほしいかといったレビューのポイント 関連するイシュー番号 担当者 このMRの責任者をアサインします。通常は作成者(レビューイ)自身をアサインします。 レビュアー コードレビューを依頼する人を指定します。 マイルストーン プロジェクトの特定のフェーズやリリース目標にMRを関連付けます。次のバージョンのリリースに向けたタスクをまとめること等ができます。 ラベル MRを分類するためのタグ付け機能です。「バグ」「ドキュメント」「緊急修正」などのラベルをつけて分類します。 マージ開始日時 マージを特定の日時にスケジュールするための機能です。特定の時間に自動でマージを実行したい場合に利用します。例えば、深夜に自動デプロイを行う際などに便利です。マージを開始するには、CI/CDのテストが成功している状態などのチェックに合格している必要があります。 マージオプション MRが承認されたときにソースブランチを削除します。 マージ完了後に、不要になった作業用ブランチを自動的に削除します。マージ後にブランチを削除し忘れることがなくなり、リポジトリを整理できます。 MRが承認されたときにコミットをスカッシュします。  マージする際に、複数のコミットを1つの大きなコミットにまとめる機能です。マージ時には1つのコミットとして履歴に記録できます。これにより、mainブランチの履歴を見やすく保てます。 ブランチ保護 以前の記事 で解説したように、mainのような重要なブランチは保護設定をすることが推奨されます。これにより、MRを経由しない直接のプッシュを防ぎ、レビューのプロセスを強制します。 Approve必須化 プロジェクトの承認ルールを設定することで、特定のチームメンバーやコードオーナーからの承認をマージに必須できます。例えば、「2人以上のレビューアの承認が必要」といったルールを設定することで、コード品質のチェック体制を強化します。この設定は、Premium, Ultimateのプランで行えます。Free版では1人の承認必須設定が可能です。 参考: https://docs.gitlab.com/user/project/merge_requests/approvals/rules/ レビュアー(レビューする人)の視点 レビュアーとしてMRをアサインされたら、以下のステップでレビューを進めましょう。 MR画面の確認 まず、MRの概要を把握します。 MRの目的、関連するイシュー、変更の概要を確認します。 失敗したCI/CDパイプラインのエラーが未解決の場合は、そこでレビューを中断し、修正を依頼します。 変更されたコードを詳細に確認します。以下の点を意識して確認するとよいと思います。 コードの品質 境界値や大規模データでの計算量が考慮されているか プロジェクトのコーディング規約に準拠しているか 変更点へのコメント 特定の変更点にコメントを付けることで、レビューイにフィードバックを伝えます。 変更された特定の行にカーソルを合わせると、コメントアイコンが表示されます。クリックすると、コメント入力欄が現れます。 修正案をコメントで提案できます。 「レビューを開始」 複数の箇所にわたるフィードバックを、まとめて一度に投稿したい場合に使うボタンです。このボタンをクリックすると、コメントはすぐに投稿されず、「保留中のコメント」として保存されます。すべてのレビューを終えた後、MRの画面の「Your review」から「レビューを送信」ボタンをクリックすると、保留中のすべてのコメントがまとめて投稿されます。 「今すぐコメントを追加」 特定のコード行に対して、すぐに投稿したい単発のコメントに使うボタンです。 明確な正解はありませんが、基本的には「レビューを開始」でフィードバックをまとめ、「今すぐコメントを追加」で緊急性の高いシンプルなコメントを送るのが良いと思います。例えば、大きめのリファクタリングでは「レビューを開始」、小さな誤字では「今すぐコメントを追加」といった使い分けができます。 「提案」 コメント入力欄にある「候補を挿入する」ボタンをクリックし、修正後のコードを記述します。これにより、ワンクリックで修正を適用できるようになります。 記述したら、その他コメントと同様にコメントを追加します。 承認(Approve) レビューが完了したら、MRを承認します。コードに修正が必要な場合は、レビューイに修正依頼を出し、修正完了の連絡をもらったら再度変更を確認して承認します。 変更が適切であると判断したら、MR画面の「承認」ボタンをクリックします。これは、コードを承認したという意思表示になります。 レビューイ(レビューしてもらう人)の視点 レビューイは、MRを作成してビューを依頼した後、レビュアーからのフィードバックに対応し、変更を完了させます。レビューが完了したらマージを行います。 MRの作成 マージするブランチのコードを確認して、レビュアーに見てもらえる状態にします。以下の点を意識して確認するとよいと思います。 パイプラインのテスト結果が成功しているか 不要なデバッグコードやコメント、一時ファイルが残っていないか レビュアーを指定してMRを作成します。MRの作成手順は 第5回 を参考にしてみてください。 コメントへの返信 質問のコメントに対しては意図を説明する返信を行います。議論が必要な場合は、返信で対話を続けます。 感謝の意を常に忘れないようにしましょう。 変更の適用 レビュアーから「提案」を受け取った場合、GitLabの機能を使って簡単に変更を適用できます。しかし、提案をそのまま適用すると1コミット単位で履歴が増えるため、コミットをまとめたい場合はローカルでの修正が必要です。「提案」機能ではコミットの粒度を制御しにくいため、ローカルでの修正との使い分けが必要です。 MRの「変更」タブで、コメントに付いている「変更を適用」ボタンをクリックします。コミットメッセージを入力して「適用」をクリックします。これで、提案された変更をコミットとして追加できます。 表示するコミットを最新バージョンに変更します。 提案された変更が適用されていることが確認できます。これで、簡単に変更を適用できました。 追加コミットと再プッシュ 複雑な修正が必要な場合や、提案をまとめて適用したい場合は、ローカルで変更を行い、再度コミットしてプッシュします。コメントに対してすべて対応が完了したら、再度レビュアーに連絡して、承認をもらいます。 マージ レビューが完了したら、MRを承認してマージします。 承認ルールが満たされ、すべてのチェックが完了したら、MR画面の「マージ」ボタンをクリックして、ブランチをマージします。 まとめ 今回は、GitLabのマージリクエストを単なるマージの申請ではなく、コードレビューの場として活用する方法を解説しました。 レビュアーは、MR画面を確認し、具体的なコメントや提案を使ってフィードバックを伝えます。一方、レビューイは、コメントに適切に対応し、修正を迅速に反映させることが重要です。MRでレビューを行うことで、レビューの履歴が残り、開発の透明性も向上します。 MRの機能を使いこなすことで、チーム全体のコード品質が向上し、効率的な開発が可能になります。 参考文献 https://docs.gitlab.com/user/project/merge_requests/reviews/ https://docs.gitlab.com/user/project/merge_requests/approvals/rules/ https://qiita.com/C_HERO/items/c5cfbdbb269efb72fb8f https://bake0937.hatenablog.com/entry/2019/10/24/145241   ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Git & GitLab 入門 (9) ~Git マスターへの道~「コードレビューの進め方」 first appeared on SIOS Tech. Lab .
アバター
はじめに 前回の記事 では、単一のジョブをステップごとに実行するシンプルなパイプラインを題材に、GitLab CI/CDの基本的な仕組みを確認しました。しかし、実際の開発現場では、アプリケーションのビルド、テスト、デプロイなど複数の処理を組み合わせ、段階的に実行することが求められます。今回はその実践編として、複数のジョブをつなぎ合わせてステージごとに実行するマルチステージパイプラインの設計方法を紹介します。さらに、作成したパイプラインを効率的に管理・運用するための実行管理のポイントについても解説します。 前提条件 本記事では、あらかじめ以下の環境が構築されていることを前提とします。環境の詳細な構築手順については、 環境構築編の記事 をご参照ください。 GitLab(Self-Managed版) LinuxサーバーにOmnibusパッケージでインストール済み Community Edition(無償版)を利用 自己署名証明書を利用し、内部DNSによる名前解決が可能 Gitlab Runner OpenShiftクラスター上にデプロイ済み Kubernetes Executorを利用し、CI/CDジョブをPodとして実行可能 レジストリ認証情報をリンクしたServiceAccountを利用可能 ex. oc secrets link gitlab-runner-sa gitlab-registry-secret –for=pull OpenShiftクラスター 閉域環境(インターネット非接続)に構築 踏み台サーバーからocコマンドで操作可能 GitLab Container Registry コンテナイメージのpush / pullに利用 自己署名証明書のため、CA証明書をRunner / ノードに登録済み 踏み台サーバー 内部DNSサーバー、NFSサーバーを兼任 外部インターネットへの接続が可能 ocコマンドでOpenShiftを操作可能 podmanでコンテナイメージの push / pull が可能 これらの環境を利用してGitLab CI/CDパイプラインを実行し、ビルドからデプロイまでの流れを検証できます。 また、本記事では以下のようにテスト用のプロジェクトとブランチを用意して検証します。 テスト用プロジェクトの作成 任意の名称で新規作成(例: test-project)。このプロジェクトでジョブを検証します。 テスト用ブランチの作成 本記事ではmulti-stage-testブランチを作成して使用していますが、mainなど任意のブランチでも検証可能です。 マルチステージパイプラインの作成方法 ここでは、実際にGitLab上でマルチステージパイプラインを作成し、アプリケーションを OpenShiftクラスターにデプロイする一連の流れを確認します。今回のサンプルでは、「イメージのビルド」と「Kubernetes へのデプロイ」をそれぞれ独立したステージとして定義します。 ディレクトリ構成 まず、プロジェクトのディレクトリ構成は以下のとおりです。 ソースコードや設定ファイルに加え、CI/CDの定義ファイル(.gitlab-ci.yml)とKubernetes のマニフェスト(deploy.yaml)を配置しています。 . ├── .gitlab-ci.yml ├── Dockerfile ├── README.md ├── deploy.yaml ├── nginx.conf └── web     └── index.html 各ファイルの役割 ファイル名 概要 Dockerfile ベースとなるNginxイメージにアプリの静的ファイルとNginx設定を組み込み、ポート8080で待ち受けるコンテナを作成します。 nginx.conf ヘルスチェック用の/healthzエンドポイントとトップページでindex.htmlを返す設定、使用ポートを定義しています。 web/index.html デプロイ成功を確認するための簡単なHTMLページです。 deploy.yaml OpenShift上にDeploymentを作成するためのマニフェストです。後述のジョブで${IMAGE}:${TAG}の部分を置換し、実際にビルドしたコンテナイメージを指定します。 .gitlab-ci.yml CI/CD パイプラインの定義です。buildステージでイメージのビルドとプッシュを行い、deployステージでKubernetesへ適用します。 Dockerfile このアプリケーションでは、ベースイメージに nginx:1.29-alpine を利用しています。閉域環境のため、本記事では事前にこのイメージをGitLab Container Registryにpushし、そのレジストリを参照する形で FROM を指定しています。 FROM registry.gitlab.local.example.com/root/test-project/nginx:1.29-alpine # アプリ静的ファイル COPY web/ /usr/share/nginx/html/ # Nginx 設定(ポート8080で待受) COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 8080 CMD ["nginx", "-g", "daemon off;"] このDockerfileでは、web/index.htmlを/usr/share/nginx/html/に配置し、Nginxをポート8080で起動することで、ブラウザやcurlからアクセスするとindex.htmlが返されるシンプルな構成になっています。 nginx.conf このnginx.confはポート8080で待ち受け、/healthzに200を返すヘルスチェック用エンドポイントを定義しています。 ドキュメントルート/usr/share/nginx/htmlに配置したindex.htmlをトップページとして返し、存在しないパスもindex.htmlにフォールバックするシンプルな設定です。 server {   listen 8080 default_server;   server_name _;   # ヘルスチェック用(200/ok)   location = /healthz {     add_header Content-Type text/plain;     return 200 "ok\n";   }   root  /usr/share/nginx/html;   index index.html;   location / {     try_files $uri $uri/ /index.html;   } } web/index.html デプロイの動作確認用に用意したシンプルな静的ファイルです。 Nginxのドキュメントルートに配置され、ブラウザやcurlでアクセスするとトップページとして返されます。パイプラインの挙動を検証したい場合は、このファイルを編集してpushすることで、新しいイメージがビルドされ、再デプロイ後に変更内容を確認できます。 <!doctype html> <html lang="ja">   <head><meta charset="utf-8"><title>Demo App</title></head>   <body>     <h1>Deploy Success v1.0.0.</h1>   </body> </html> deploy.yaml アプリケーションをOpenShiftクラスター上にデプロイするためのDeploymentマニフェストです。spec.template.spec.containers[0].imageには ${IMAGE}:${TAG}を指定しており、CI/CDパイプライン実行時にビルドしたイメージ名へ置換されます。 コンテナはポート8080を公開し、/healthzへのHTTP応答をreadinessProbeとして利用することで、Pod が正常に起動しているかを判定します。 apiVersion: apps/v1 kind: Deployment metadata:   name: multi-stage-demo-deploy   namespace: gitlab-runner-test spec:   replicas: 1   selector:     matchLabels:       app: multi-stage-demo   template:     metadata:       labels:         app: multi-stage-demo     spec:       serviceAccountName: gitlab-runner-sa       imagePullSecrets:         - name: gitlab-registry-secret       containers:         - name: multi-stage-demo-app           image: ${IMAGE}:${TAG}           imagePullPolicy: Always           ports:             - containerPort: 8080           readinessProbe:             httpGet:               path: /healthz               port: 8080             initialDelaySeconds: 3             periodSeconds: 5 .gitlab-ci.yml この.gitlab-ci.ymlは 2ステージ(build → deploy)構成でdindを使ってイメージをビルド→レジストリへpush →OpenShiftへのデプロイまでを自動化します。まず定義全体を示し、その後に実行フローを解説します。 stages:   - build   - deploy default:   tags: [devsecops-runner] build_image:   stage: build   image: registry.gitlab.local.example.com/root/registry-project/docker:28.3.3   services:     - name: registry.gitlab.local.example.com/root/registry-project/docker:28.3.3-dind       alias: docker       entrypoint: ["/bin/sh","-lc"]       command:         - >           cp /etc/gitlab-runner/certs/gitlab.local.example.com.crt /usr/local/share/ca-certificates/ca.crt &&           update-ca-certificates ;           exec dockerd-entrypoint.sh           --tls=false           --host=unix:///var/run/docker.sock           --host=tcp://0.0.0.0:2375   variables:     DOCKER_HOST: tcp://docker:2375     DOCKER_TLS_CERTDIR: ""   before_script:     - cp /etc/gitlab-runner/certs/gitlab.local.example.com.crt /usr/local/share/ca-certificates/ca.crt && update-ca-certificates     - docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"     # IMAGE_VERSION が定義されていればそれを利用、なければ CI_COMMIT_SHORT_SHA     - export IMAGE_TAG="${IMAGE_VERSION:-$CI_COMMIT_SHORT_SHA}"     - export IMAGE_FULL="${CI_REGISTRY_IMAGE}/demo:${IMAGE_TAG}"   script:     - docker build -t "$IMAGE_FULL" .     - docker push "$IMAGE_FULL"     - printf "IMAGE_FULL=%s\n" "$IMAGE_FULL" > build.env   artifacts:     reports:       dotenv: build.env deploy_manifest:   stage: deploy   image: registry.gitlab.local.example.com/root/test-project/oc:4.18   needs:     - job: build_image       artifacts: true   variables:     K8S_NAMESPACE: gitlab-runner-test   before_script:     - oc whoami   script:     - |       : "${IMAGE_FULL:?IMAGE_FULL missing from build.env}"       # IMAGE と TAG を分離       IMAGE="${IMAGE_FULL%:*}"; TAG="${IMAGE_FULL##*:}"       # ${IMAGE}:${TAG} を合成       sed "s|\${IMAGE}:\${TAG}|${IMAGE_FULL}|g" deploy.yaml > deploy.rendered.yaml       echo "---- rendered ----"       cat deploy.rendered.yaml       oc apply -f deploy.rendered.yaml ※IMAGE_VERSIONが未定義の場合はCI_COMMIT_SHORT_SHAがタグに使われます。この場合、短いコミットIDごとに新しいイメージが作成されるため、レジストリの容量管理や不要イメージの削除に注意してください。レジストリの容量管理については GitLab Container Registry: 応用編(可視性設定とガベージコレクション) をご参照ください。 補足: 閉域環境向けの準備 ベースイメージ登録 通常はDocker Hubから直接nginx:1.29-alpineを取得できますが、インターネット接続ができない環境では以下のように 事前にレジストリにpushしておきます。 $ podman login registry.gitlab.local.example.com $ podman pull docker.io/library/nginx:1.29.1-alpine $ podman tag docker.io/library/nginx:1.29.1-alpine \ registry.gitlab.local.example.com/root/test-project/nginx:1.29.1-alpine $ podman push \ registry.gitlab.local.example.com/root/test-project/nginx:1.29.1-alpine ※Docker 利用環境ではpodman → dockerに置き換えてください。 ocコマンド用イメージ登録 通常はregistry.redhat.ioから直接ose-cli-rhel9:v4.18を取得できますが、インターネット接続ができない環境では以下のように 事前にレジストリにpushしておきます。 $ podman login registry.redhat.io $ podman pull registry.redhat.io/openshift4/ose-cli-rhel9:v4.18 $ podman login registry.gitlab.local.example.com $ podman tag registry.redhat.io/openshift4/ose-cli-rhel9:v4.18 \   registry.gitlab.local.example.com/root/test-project/oc:4.18 $ podman push registry.gitlab.local.example.com/root/test-project/oc:4.18 ※Docker利用環境ではpodman → dockerに置き換えてください。 ※デプロイ先のコンテナ基盤がKubernetesである場合はoc → kubectlに置き換えてください。OpenShiftの場合もkubectlコマンドで基本的な操作は可能ですが、ocにはOpenShift特有の拡張機能が含まれています。 パイプラインの仕組み(実行フロー解説) パイプラインは 2ステージ構成 になっています。 1. build ステージ(イメージのビルドとプッシュ) ジョブbuild_imageが実行されます。 Docker-in-Docker(dind)環境を利用してdocker buildを実行し、GitLab Container Registryにイメージをpushします。 pushしたイメージのフルパス(IMAGE_FULL)をbuild.envとしてアーティファクトに保存します。 → この情報が次のステージに引き渡されます。 2. deploy ステージ(マニフェストの適用) ジョブdeploy_manifestが実行されます。 先ほど保存したIMAGE_FULLを利用し、deploy.yaml内の${IMAGE}:${TAG}を実際のイメージ名に置換します。 oc apply -f deploy.rendered.yamlを実行してOpenShiftクラスターにDeploymentを作成します。 Podが立ち上がり、readiness probeによって/healthzが成功すればデプロイ完了です。 パイプラインの実行 作成したパイプラインを実際に動かしてみましょう。 まず、検証用プロジェクトに移動し、管理画面からCI/CD変数を設定します。[変数を追加]をクリックし、キーにIMAGE_VERSION、値にv1.0.0を入力します。なお、mainブランチなどの保護ブランチ以外で試す場合は、保存時に[変数の保護]のチェックを外してください。チェックが付いたままだと、featureブランチなど非保護ブランチでパイプライン実行時に環境変数を参照できなくなります。 次に、ソースコードをリポジトリにpushします。GitLabのプロジェクト画面から検証対象のブランチに切り替え、[編集] → [Web IDE]を選択して内部エディタを開きます。前述のファイル(.gitlab-ci.ymlやdeploy.yamlなど)を作成し、右側の[Source Control]アイコンからコミットメッセージを入力して[Commit and push]をクリックすれば、コードがブランチにpushされます。 ソースコードがpushされると、自動的にパイプラインが起動します。プロジェクトのサイドバーから [ビルド] > [パイプライン] を選択すると、実行中のパイプラインを確認できます。さらに、パイプラインIDをクリックすれば、各ジョブの実行状況やログを確認できます。 プロジェクトのサイドバーから[デプロイ] > [コンテナレジストリ]を選択すると、プロジェクト内レジストリのリポジトリ一覧が表示されます。今回ビルドしたイメージはdemoリポジトリに格納されています。 この例では、build_imageジョブでイメージをビルドしてレジストリにpushし、その結果生成されたIMAGE_FULL変数がbuild.envに保存されます。続くdeploy_manifestジョブでは、その変数を利用してマニフェスト内のプレースホルダーを置換し、oc applyコマンドでOpenShiftにデプロイできていることが確認できます。 デプロイ成功の確認 デプロイジョブの成功を確認した後、アプリのPodがRunning状態で起動していることを確認します。 $ oc get pod -n gitlab-runner-test -l app=multi-stage-demo NAME                                       READY   STATUS    RESTARTS   AGE multi-stage-demo-deploy-6874887f67-w7br8   1/1     Running   0          69s Podが正常に起動すると、Pod内のNginxでweb/index.htmlが配信されます。以下のようにアクセスして動作を確認できます。 # Pod名を取得 $ POD=$(oc -n gitlab-runner-test get pod -l app=multi-stage-demo -o jsonpath='{.items[0].metadata.name}') # ローカル18080 → Pod 8080 へ転送 $ oc -n gitlab-runner-test port-forward pod/$POD 18080:8080 # ブラウザからlocalhost:18080にアクセスし、index.htmlの内容が表示されることを確認 Deploy Success v1.0.0. このメッセージが表示されれば、マルチステージパイプラインを通じて「ビルド→レジストリへのpush→OpenShiftへのデプロイ」が自動化できていることを確認できます。 これで、コードのpushをトリガーにビルドからデプロイまでが一連の流れで実行されることを、実際のパイプライン実行を通して確かめられます。 なお、すべての処理を1つのステージにまとめることも可能ですが、ビルドとデプロイを分けることで以下のメリットがあります。 責務の分離: ビルドとデプロイを明確に分けることで、どの段階で失敗したのかを特定しやすくなります。 効率的なリトライ: ビルドが成功していれば、デプロイだけを再実行できるため、再試行の効率が向上します。 並列・拡張性の確保: 将来的にテストステージを挟んだり、複数環境へのデプロイを分岐させたりといった拡張が容易になります。 このように、ステージを適切に分割することで、パイプラインの信頼性と運用効率を高めることができます。 まとめ 本記事では、複数のステージを組み合わせたパイプラインの設定方法を解説しました。 サンプルアプリケーションを題材に、ビルドとデプロイを別ステージに分けたマルチステージパイプラインを構築し、実際にコードのpushをトリガーにして一連の処理が自動で実行される流れを確認しました。 単一ステージに処理をまとめることも可能ですが、ステージを分割することで「どこで失敗したのかが明確になる」「ビルドが成功していればデプロイのみを再実行できる」といった運用上のメリットが得られることも示しました。これにより、パイプラインの信頼性や管理性が大きく向上します。 次回は、さらに複雑化したパイプライン定義ファイルを include / extends 機能 を活用して整理する方法を解説します。複数のジョブやステージが増えて管理が煩雑になったときに役立つ実践的なテクニックを取り上げ、よりスケーラブルなCI/CD運用に向けた一歩を紹介します。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post GitLab CI/CD 実践[マルチステージ編]:複数ジョブをつなぐパイプライン設計 first appeared on SIOS Tech. Lab .
アバター
初めに 前回のブログでは「 Claude Code革命!3フェーズ開発で効率的な開発:計画→実装→検証術 」について紹介しましたが、今回は実際にClaude Codeで仕様書ベース開発運用する際に「これは絶対に押さえておかないとハマる」というポイントについてお話しします。 実際に検証していて失敗したことや、気をつけないと時間を無駄にしてしまうポイントを中心にまとめました。 1. ドメイン知識の明示的なドキュメント化の重要性 この方法で検証していて失敗したこともあります。例えば、 プロジェクトの基礎的な知識(ドメイン知識)は、明示的にドキュメント化しない限りAIは理解してくれません 。 実際あった問題として、ネイティブアプリとWebアプリのバックエンドリンクの構成があります。ローカル環境ではSWCでエミュレートしていて、「/api」に自動でプロキシされる仕組みでしたが、AIはそれを知らずにバックエンドURLを直接埋め込もうとして、 APIパスの参照エラーが多発 しました。 これは「プロジェクトコア」のようなドキュメントを作成して共通知識を提供することで解決しました。 AIは書かれていないことは認識できず、セッション内で与えていない情報は理解しません 。 プロジェクトコアドキュメントの具体例 プロジェクトコアには、実際にデプロイする環境のプロキシの設計やプロジェクトの根幹に関わる部分をちゃんと定義しておくべきです。 今回私が作った環境では、Azure Static Web Appsをバックエンドリンクで構築していて、スラッシュAPIというのが自動でプレフィックスで飛んでいくという仕組みがあります。そのため、プレフィックス「/api」でアクセスするということを明記したり、プロジェクト構成みたいなのを書いておいて、そういった情報をAIに与えています。 当たり前のように思える環境設定や開発ルールも、AIにとっては「初めて聞く話」です。人間の開発者なら暗黙知として共有されている部分も、AIには明示的に教える必要があります。 2. AIがドキュメントを無視する問題への対処 計画フェーズでは「計画.md」などのファイルに指示を書いていますが、 AIは時々ドキュメントを無視することがあります 。人間と同じで、指示や定義を見ないこともあるんです。読んだうえで無視することもあるので、 絶対守ってほしいことはドキュメント化し、プロンプトでも注意するのが重要 です。 これは本当にイライラするポイントで、せっかく時間をかけて詳細な仕様書を作っても「それ、無視しちゃダメでしょ!」ということが頻繁に起こります。 無視されやすいパターンと対策 プロンプトに期待してない情報は割と無視しますね。そのパターン的なミスの傾向みたいなのがあったら、マークダウンファイルに情報反映させるというやり取りをよくやっています。 仕様書を書いてもらうフェーズと開発フェーズで、仕様書を書いている最中にコードの編集をしたりしていたんですよ。そこで、仕様要件フェーズと開発フェーズの三つに分けますという指示をつけて、計画フェーズではファイルの編集は加えないでくださいという指示を追加しています。開発フェーズは、作成した仕様のドキュメントを読んで、それに対してステップバイステップで開発を進めてくださいということを、マークダウンファイルで定義しています。 対策としては: 最重要な制約事項はドキュメントに書く さらにプロンプトでも再度強調する 「この部分だけは絶対に守ってください」という明示的な指示を含める 二重、三重の安全策を講じることが大切です。 3. 仕様書の適切な分量バランス 仕様書の分量については、 長すぎるとAIが無視する確率が上がります 。「無視しました」という返答が返ってくることもあり、それを見たときは正直 ブチ切れました (笑)。 短ければ理想的ですが、短すぎると時間がかかるので、AIが無視する可能性も考慮しながら適切な分量を見極める必要があります。 どの程度の分量が適切かはプロジェクト依存 です。ドメイン知識が多ければ、その分仕様書に書く情報は少なくて済みます。 具体的な分量の目安 私の環境で言うと、 エンドポイント2つと、それに対応する画面1つ という感じだと、体感的に上手くいったという印象です。これは本当にプロジェクトによるというか、プロジェクトコアによる感じの内容というか、元のコンテキスト量が影響してきます。 この辺りは経験則になってしまいますが、AIが「長いから読みたくない」と判断するラインを見極めることが重要です。人間と同じで、あまりにも長い仕様書は最後まで読んでもらえません。 4. 新機能開発とバグレポートの使い分け 私は新機能開発とバグレポートをこの二つの方法で分けて対応しています。 新機能開発 : 必ず3フェーズ(計画→実装→検証)を踏む 小さな変更 : でもドキュメント→実装という段階を踏む 本当に小さな変更 : 人間がやったほうが早い 人間がやったほうが早い変更の見極め プロジェクト構成的な部分の変更ですね。コード規約みたいなところで、ちょっと上の階層にファイルを移し替えたりとか、ファイル構成で、ちょっとこっちに移行させるほうがいいよねみたいな話とか、ファイルの単純な移動は、VS Codeの補完機能が優秀なので、そういった作業とか、あとは関数名が気に入らないので、関数名のリネームするという作業ですよね。 人間が手を動かして作業して、セッションが継続しているのであれば、ちゃんと変更を加えましたよということをAI側に伝えてあげる必要はあります。そうじゃないと、人間が編集したファイルとAIが編集しようとしているファイルでコンフリクト起きてしまうので、再度ファイルを作ろうとするんですよ。なので、そういったところで調整を取っていく必要はあるかなと思います。 この使い分けが重要で、何でもかんでもAIに頼めばいいというものではありません。1行2行の修正をAIに説明するより、自分でやってしまったほうが早いケースも多々あります。 プロセスを踏んでも意図したものができない場合は、やはり人間のドキュメントが不十分だということです。AIは書かれていないことを自由に判断するので、ドキュメントの質を高める必要があります。 5. 中規模開発での威力と現在の限界 現在はプライベートリポジトリで検証しているため、 大規模プロジェクトへの導入経験はまだありません が、中規模程度の開発であれば強力なツールになると思います。特に プロトタイピングでは大きな力を発揮しそう です。 個人的に学びになった点としては、仕様書作成が苦手な私でも、AIが返してきた仕様書を見て「分かりやすい」と感じることがあります。 学習的な側面でも価値がある と思います。 完璧な仕様書があれば理想的ですが、そういうものは実際には存在せず、どこかに不備があるものです。だからこそ、機能ごとに段階的に仕様書を作っていくアプローチが有効だと思います。 6. よくある失敗パターンとその対策 型定義の不整合問題 本当によくあるのが、フロントエンドとバックエンドで型定義が共通化されてなくて、バックエンドにアクセスできない、APIアクセスは成功してるんだけども、画面に表示がされないということがありました。 対策としては、 OpenAPI スペックを作らせて、そのOpenAPIスペックから型定義を作成する 。 そして、フロントエンドはその型定義を絶対に使用するようにする、という感じで回避しています。 デプロイ環境の差異による問題 デプロイ環境の差異みたいなところで問題が起きることもあります。今回Azure のバックエンドリンクで、スラッシュAPIのコンテンツを自動でプロキシしてくれるんですけど、そういったことを伝えてなくて、なんか別のエンドポイントベースURLみたいなのを付けて、そこにアクセスするようにしましょうみたいな提案をされました。 バックエンドが現状、localhost の3001番で動いてるので、ローカル3001番に直接アクセスするように変えちゃいましょう、みたいなことを言われることがあります。これはプロジェクトコアドキュメントでしっかりと環境構成を明記しておくことで回避できます。 まとめ Claude Codeは確実に開発効率を向上させてくれるツールですが、これらのポイントを押さえておかないと、余計な時間を費やしてしまいます。特にドメイン知識の明示化と仕様書の分量バランスは、成功の鍵となる重要な要素です。 まぁ暴走するのは人間と一緒って感じですね。人間よりも暴走しがちですが、言いやすい相手ですよねw 皆さんも、ぜひこれらのポイントを参考にClaude Codeを活用してみてください! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Code仕様書ベースでハマる6つの落とし穴!失敗回避の備忘録 first appeared on SIOS Tech. Lab .
アバター
はじめに ども!AIとの開発をがっつり初めて2か月で毎日Claude Codeとお話している龍ちゃんです。本業とは別で開発を進めているのですが、今まで1週間で頑張って1件の検証開発しかできなかったんですが、2日で検証したいことをサンプル付きで作成できるので最高ですね。これまでの開発経験で技術記事も数多く書いてきましたが、今回は特に効果を実感したAIとの協働について書いていこうと思います。 ちなみに「 Claude Code革命!3フェーズ開発で効率的な開発:計画→実装→検証術 」Claudeに実装させるフェーズを分割して開発をする手法を紹介しています。今回はそこの計画書執筆フェーズのお話です。 皆さんは、仕様書を書くことに対してどんな印象をお持ちですか?正直に言うと、入社して4年ですが、いまだに仕様書を書くという作業に対して苦手意識があります。仕様書を書くのが好きというエンジニアに個人的にあったことがありません。「完璧な仕様書を書くぞ~!」というモチベーションを持ったとしてもアレルギーといいますか、「完璧な仕様書」というものを書くのはハードルが高いですね。 背景・課題説明 仕様書が必要な理由 その一方でAIと共同で開発を進めていくためには「仕様書」があったほうが良いです。コード規約やLinter/Formatterが整備されているプロジェクトであれば、コードが仕様書の機能を持つことがありますが、プロジェクト初期の段階であれば仕様書を読み込ませて開発をするほうが圧倒的に開発効率が良いです。Vibe Codingで単純なプロンプトで100-300文字のプロンプトで作成するのは不可能です。 機能開発中によくあるのが、検討不足や考慮不足によって開発中にSlackでの相談やミーティングを挟んだり、手が止まって考え込んだりすることではないでしょうか。コードの書き方で悩むのは問題ありませんが、事前に決めておくべき情報が未確定なために発生する手戻りは避けたいものです。 仕様書アレルギーの原因分析 仕様書を書くことに対してアレルギーがある原因を個人的に分析をしてみると、仕様書を読み込んだ経験があまりないことがあります。より良い仕様書を書くためには、良い仕様書のお手本が必要です。じゃあそのより良い仕様書ってどこにあるのって話ですよね。完璧超人が執筆した仕様書があれば理想ですね。(レビューなしで完璧な仕様書を書ける人がいるならあってみたい…) そんな可能性はないので、プロジェクトではレビューを重ねてより良い仕様書を目指していくのが、普通の流れになると思います。ということを踏まえて、皆さんの周りに仕様書ってありますか?仕様書を読み込む経験ってあまりないんじゃないでしょうか? 技術選択の理由:なぜAIと協力するのか そこで提案です!小さく仕様書を書いてみませんか?いきなり完璧な仕様書なんて不可能ですし、レビューアーを確保するのも大変ですよね。そこでAIを活用します。 AIを活用した仕様書作成フロー AIに仕様書を書いてもらい、それをレビューする。私たちは意図を伝えて仕様書を作成してもらい、人間がレビュアーとして参加し、AIと協力する形で仕様書を作成していくフローです。 実装詳細 CLAUDE.mdの具体的な記述例 前提としてAIはコードを書きたがります。設計段階では、目的や禁止事項をCLAUDE.mdに定義しています。 実際に私が使っているCLAUDE.mdの中身を見てみましょう: # 設計フェーズのルール ## 目的 AIに人間の意図を適切に伝えて効率的な開発を行う ## 設計フェーズで行うこと - 型定義の設計 - データベース構造の設計 - API 仕様の定義 - アーキテクチャ設計 - 機能要件の明確化 - 非機能要件の定義 ## 設計フェーズで禁止すること - ❌ 実装コードの記述禁止 - ❌ 具体的なロジックの記述禁止 - ❌ ライブラリの選定禁止 - ❌ 具体的な関数実装禁止 ## レビューポイント - 要件の抜け漏れはないか - 設計の整合性は取れているか - スケーラビリティは考慮されているか - セキュリティ要件は満たしているか このように明確にルールを定義することで、AIが設計に集中してくれます。 仕様書作成の具体的な手順 要件の整理 :何を作りたいかを箇条書きで整理 AIとの対話 :CLAUDE.mdのルールに基づいて仕様書を依頼 レビューと修正 :作成された仕様書を人間の視点でレビュー 反復改善 :不足部分や曖昧な部分を繰り返し修正 仕様書のテンプレート例 # 機能仕様書:[機能名] ## 概要 [機能の目的と概要] ## 機能要件 - [要件1] - [要件2] - [要件3] ## 非機能要件 - パフォーマンス要件 - セキュリティ要件 - 可用性要件 ## データ構造 [必要なデータ構造の定義] ## API仕様 [エンドポイントの定義] ## 制約事項 [技術的制約や業務的制約] 動作確認・検証 実際の効果を検証してみた 従来の開発フローと比較してみました: 項目 Before(従来の人間だけでの開発) After(AIと協力した仕様書駆動) 仕様検討 開発中に随時(割り込み多数) 事前に1-2時間 開発時間 1週間 2日 手戻り回数 平均3-4回 平均1回 特に 開発時間の短縮 と手戻り回数が顕著に現れました! まだまだ検証中の段階なので、小規模な検証なことは留意しておいてください。 AIと協力する副次的効果 仕様書を書くことの効果は、開発前に作成したい機能の整理ができることです。 AIと一緒に仕様書を作成する副次的効果として、AIが作った仕様書をレビューする経験が得られます。仕様書の段階で、こちらの意図が適切に伝わっていなければレビューして修正します。これにより開発前に検討不足や考慮不足を抑えることができます。完璧なレビューは不可能ですが、それは経験を重ねることで改善していくものですね。 成功事例:実際のプロジェクトから 最近の検証プロジェクトでは、以下のような成果が得られました: ユーザー認証システム :仕様書作成1時間 → 実装1.5日 データ分析ダッシュボード :仕様書作成2時間 → 実装2日 API統合機能 :仕様書作成1.5時間 → 実装1日 いずれも従来の3-4倍の速度で完成させることができました。 課題と今後の展望 現在の制限事項と改善案 まだ完璧ではありません。AIの理解度に依存する部分があり、複雑な業務ロジックは人間の補完が必要です。また、チーム内での標準化やレビュー観点の統一も課題ですね。 短期的には仕様書テンプレートの標準化とAIプロンプトの最適化を進めています。 いっそのこと 、将来的にはAIが要件定義から運用まで一貫してサポートしてくれるような環境を構築したいですね。 まとめ 今回は、AIと協力した仕様書作成フローについて詳しく見てきました。 「仕様書アレルギー」を克服し、効率的な開発を実現する方法として: 小さく始める仕様書作成 :完璧を目指さず、まずは基本的な要件から AIとの協働レビュープロセス :AIに作成してもらい、人間がレビューする 設計フェーズでの明確なルール設定 :CLAUDE.mdでの禁止事項と目的の明示 段階的な開発プロセス :設計→開発→ブラッシュアップの3段階 これらの知識を活かして、皆さんもAIと一緒に仕様書作成にチャレンジしてみてください!最初は慣れないかもしれませんが、開発効率の向上を実感できると思います。 実際のプロジェクトでどちらを選ぶべきか、迷うところですよね。でも、一度この方法を試してみれば、その効果を実感していただけるはずです。 次回は、実際の開発フェーズでのAI活用術について書く予定です。お楽しみに! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post AI協働で仕様書アレルギー克服!開発時間を1週間→2日に短縮する実践法 first appeared on SIOS Tech. Lab .
アバター
初めに AIと一緒に開発をするようになってから、フロントエンドとバックエンド両方を爆速で開発することができるようになって、検証が爆速で進むようになった龍ちゃんです。 AIが混乱しないようにプロジェクト自体を整備する方法についてお話しします。AIと一緒に開発を進める開発手法に関しては、以下の記事で解説をしています。 Claude Code革命!3フェーズ開発で効率的な開発:計画→実装→検証術 AI協働で仕様書アレルギー克服!開発時間を1週間→2日に短縮する実践法 Claude Code仕様書ベースでハマる6つの落とし穴!失敗回避の備忘録 AIに触らせないファイルを作ることで過剰な生成を禁止したり、自動生成パイプラインを構築して人為的なミスを防ぐなど、プロジェクト構造レベルでの対策が重要です。 実際に発生した問題事例:型定義の齟齬 まず、実際に私が遭遇した問題から紹介します。 環境構成 フロントエンド : Next.js バックエンド : Nest.js 発生した問題 フロントエンドとバックエンドで 型定義の齟齬が発生 していました。バックエンドで定義した型をフロントエンド側で再定義して、変更が反映されておらず 参照エラーが発生 する状況でした。 この問題の根本原因は、AIが各環境で独立して型定義を生成してしまい、バックエンドの型定義変更がフロントエンドに反映されないことでした。人間の開発者なら「バックエンドで型が変わったから、フロントエンドも更新しなきゃ」と気づけますが、AIは各ファイルを独立して見てしまいます。 解決策:自動生成パイプラインの構築 この問題を解決するため、以下の自動生成パイプラインを構築しました: 1. OpenAPI Spec自動生成 Nest.jsからOpenAPI Spec を自動生成する仕組みを導入しました。これにより、バックエンドのAPI仕様が変更されると、自動的にスペックファイルも更新されます。 公式で提供されているので、コードレベルでOpenAPI Specを生成することができます。 2. フロントエンド側の自動生成 Orval を使用して、Next.jsに SWR + Axiosのリクエスト・型定義を自動生成 する仕組み を構築しました。OpenAPI Specから自動的にフロントエンド用のコードが生成されるため、バックエンドとフロントエンドの型定義が必ず一致します。 このシステムでは、SWRとAxiosを使ってAPIリクエストを行っており、データフェッチャーやカスタムフックが自動で提供されるため、非常に便利な仕組みになっています。 3. Claude への通知 最も重要なのは、 Claudeに変更不可と明確に通知 することです。自動生成されるファイルには、コメントやCLAUDE.mdファイルで「このファイルは自動生成されるため変更禁止」と明記し、Claudeが勝手に編集しないように徹底しました。 自動生成するためのコマンドと、どのファイルが変更不可なのかを明確に指定する必要があります。 プロジェクト構成の最適化 AIが迷わないよう、プロジェクト構成も工夫しています: / ├── CLAUDE.md # プロジェクト全体のガイドライン ├── docs/ # 計画・設計フェーズ │ ├── CLAUDE.md # 計画フェーズ専用ルール │ └── api/ # OpenAPI Spec └── application/ # 実装フェーズ ├── backend/ │ └── CLAUDE.md # バックエンド実装ルール └── frontend/ └── CLAUDE.md # フロントエンド実装ルール 各フェーズ用のCLAUDE.mdファイル配置 各ディレクトリに CLAUDE.md ファイルを配置し、そのディレクトリで作業する際の固有ルールを記載しています。例えば: application/frontend/CLAUDE.md : 自動生成ファイルの変更禁止、使用可能なライブラリの制限など application/backend/CLAUDE.md : API仕様変更時の手順、データベーススキーマ変更の注意点など docs/CLAUDE.md : ドキュメント作成時のフォーマット、必須項目など AIに触らせないファイルの明確化 過剰な生成を防ぐファイル管理戦略 として、以下のような対策を実施しています: 自動生成ファイルには必ず「DO NOT EDIT – Auto Generated」のコメントを付与 パッケージファイル(package.json等)の変更制限 設定ファイル類の変更制限 各CLAUDE.mdで変更不可ファイルのリスト明記 ただし、ここまで書いていたとしても、AIは結構無視することがあります。実際に、自動生成して編集禁止にしている設定ファイルを編集しに行って動くようにしたりとか、ダイナミックな手法をやってきたりするので、いくら書いていたとしても無視をする可能性があることは念頭においた方が良いと思います。 大規模プロジェクトでの課題と対策 フロントエンド・バックエンド開発者が異なる場合の同期 大規模プロジェクトでは、フロントエンドの開発者とバックエンドの開発者が違う場合に、いかに同期を取っていくかが重要な課題となります。 開発順序の調整 現在のシステムだと、バックエンドの開発をしてからフロントエンドの開発をするという順番になるため、この順序をどう合わせていくかが必要です。 同時開発のためのアプローチ 同時に開発を進めていくためには、以下のような手法が有効です: モック を使用した並行開発 型定義を先に作成 してOpenAPI仕様書だけを先に渡す Orvalで生成 したフロントエンドコードを使ってバックエンドと協調開発 このアプローチにより、フロントエンドとバックエンドの同時進行での開発が可能になります。 この手法の効果 自動生成パイプラインとプロジェクト整備により: 型定義の齟齬が完全に解消 AIが余計なファイルを触ることによる意図しない変更の防止 人間が後から「なぜこの変更をしたのか分からない」状況の回避 コードレビュー時の確認ポイントの削減 バックエンドを定義したら、そこからフロントエンドを並行して開発できますし、バックエンドとフロントエンドで型定義が異なるという問題がほとんどなくなりました。もちろん、バックエンドの定義自体が間違っていれば動作しませんが、フロントエンド側での型の不一致はかなり抑制できたと感じています。 これまでは自動生成の仕組みを使わずに開発していたため、コードが若干汚くなる傾向があり、フロント側で型定義の再定義が行われて連携が取れていないという問題や、型ファイルが増えていくという課題がありました。この仕組みにより、プロジェクト全体がより整理されたファイル構造になり、可読性が向上したと実感しています。 特に型定義の自動同期により、フロントエンドとバックエンドの開発を並行して進められるようになりました。 まとめ 正直、これは導入してみて一番良かったなと思える点ですね。ルールをあまり追加させずにAIに生成させるコードが圧倒的にきれいになりました。 ルールをガッチガチにしてコードをきれいにするというのも今後の検証として取り込んでいきます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post AIと爆速開発!Next.js×Nest.js型定義同期の自動生成パイプライン構築術 first appeared on SIOS Tech. Lab .
アバター
はじめに ども!毎日毎日Claude Codeとお話して日課となっている龍ちゃんです。直近ではClaude Codeに関するお話を執筆していこうと思います。 最初は「これは革命的だ!」と思って飛び込んだClaude Codeでしたが、実際に使い込んでいくと、思った以上に奥が深くて、適当にプロンプトを投げているだけでは思うような成果が出ないことがわかってきました。 今回は、私が実際にClaude Codeを使い倒してきた中で見つけた、「Vibe Coding」から卒業するための実践的なTipsをまとめてみました。同じような課題を感じている方の参考になれば幸いです。 今回紹介する問題点・課題を解消するために検証した内容をまとめています。こちらも併せて読んでもらえると楽しいかもしれません。 Claude Code革命!3フェーズ開発で効率的な開発:計画→実装→検証術 AI協働で仕様書アレルギー克服!開発時間を1週間→2日に短縮する実践法 Claude Code仕様書ベースでハマる6つの落とし穴!失敗回避の備忘録 AIと爆速開発!Next.js×Nest.js型定義同期の自動生成パイプライン構築術 Vibe Codingの落とし穴 雑なプロンプトでは成果が出ない現実 「とりあえずやってみる」テンション感で始めがちなClaude Codeですが、これが最初の落とし穴でした。数行のプロンプトで開発に十分な意図が伝わっていないんですよね。 例えば、「4輪駆動で走る車を作って」と言っているようなもので、具体的な仕様や制約が伝わっていない状況になってしまいます。これでは、Claude Codeも困ってしまいますよね。 ドキュメント化が成功の鍵 解決策として見えてきたのが、 Claude Codingの前にドキュメント化しておく ことの重要性です。 具体的には、以下のような準備が必要になります: 既存のコードがある場合 /initはとりあえず打つ! 既存コードを読み取らせてドキュメントを作っておく Azureなどの構成などもある場合はドキュメント化しておく コーディングの前にタスク専用の設計書を作成する 設計書→Codingの流れを徹底する まずは設計書を作成して内容が人間の意図しているものと一致しているか確認しておく Claude Codeはコードを書きたがるから、設計書のみに中止させる Vibe Debugがつらすぎる問題 よくあるデバッグ地獄 Vibe Codingしていて、動かないことがそれなりにあります。エラー内容を入力して修正してもらうこともできますが、治らない場合は大胆な戦略をとることがあるんです。 例えば: フロントの改修をしているのに、バックエンドのコードを直そうとする 新規ファイルを作成してバージョンアップしたりする Bicepファイルを編集するときに、いったんリソースグループを削除してしまう 効果的なデバッグ戦略 エラー→Vibe Codingがつらくなる場合は、該当箇所のコードを読み込んで、 人間の観点+エラーメッセージ+調査指示 で取り組むことで精度が上がることがわかりました。 セッション管理の重要性 メモリ制限を理解する ドキュメント化していない知識は伝わっていないと思ったほうが良い です。Claude Codeはセッション型でメモリに記憶を保持していないので、セッションを閉じると記憶が失われると思ったほうが良いですね。 そのため、定期的なドキュメント管理とプロジェクトのコア部分の情報をドキュメント化して読み込ませておくことが重要になります。 適切なタスクサイズ 1セッション1タスク ぐらいの分量で収まるように進めることを意識しています。ドキュメント→タスクを完了させる動きをさせておくのがコツです。 セッションを閉じるとタスクの進捗が確認することができないので、セッションを閉じるときはタスクが完了したタイミングであることを意識しておきます。 巨大なタスクでなく、 2~3hで完了させる程度 でタスクのサイズを分割して進めるのが良いですね。タスクが大きすぎると、Claude Code側がフェーズを分割したりするので、フェーズ進行中はセッションを切らないようにしています。 実践的なTips集 不要ファイル・デバッグコンソールの管理 Vibe Debugの結果、不要なコードや不要なファイルが生成されていることがあります。これは、最終的にコミットやPRに含まないことが大切です。 最後に「参照していないコードを削除しておいてください。不要なファイルは削除してください」と指示することで、きれいな状態を保てます。 ディレクトリ単位で不要になったファイルは削除しておくことも重要です(過去のプロジェクトなどのファイルがある場合は削除しておきましょう)。 フロントとバックの型定義の不整合対策 バックエンドとフロントエンドでAPIの型が不整合が発生していたことがありました。 対応策: フロントのコードを作成する前にバックエンドのソースを読ませる バックエンドのAPIへアクセスする部分は自動生成させてそれを使用するように変更する(検討中) CLAUDE.mdの活用と注意点 特にセッションが長くなった場合は CLAUDE.mdを無視しがち になります。AIは昔のコンテキストほど優先度が下がるというのはよくある話ですね。 対応策: セッションが長くなった場合はいったん切る セッションの開始時には必ずCLAUDE.mdを読み込まれるので、セッション内で編集するファイルの領域を決定する バック→フロントの連続ではなく、バック作成→OpenAPI Spec→フロントという連携をする ただし、 セッション開始時からCLAUDE.mdを無視することもあります 。そういった場合は、追加のプロンプトで指示を与えることが効果的です。 具体的には: いったん処理を止めて、追加のプロンプトで再指示 「無視されているCLAUDE.mdを再度読み込んでください」といった明示的な指示 重要なルールを#コマンドで再度強調する これらの方法で、CLAUDE.mdの内容を確実に反映させることができます。 ファイルスコープの明確化 編集するファイルと触らないファイルを決定する ことが重要です。例えば: ビルド後のファイルを直接変更しようとした フロントの改修中にバックエンドのコードを変更しようとした このような問題を避けるために、事前にスコープを明確にしておきます。 プログラミングファイルによる違い Bicepファイルは難しい Bicepファイルの依存関係周りの設定が難しいことがわかりました。 回避策: 依存関係やリソースが完成した後で連携する処理はShell ScriptでAzure CLI経由で処理を行う Bicepの処理はリソースの作成のみに注力させておく GitHub Actionsも要注意 GitHub Actionsについても課題があります: 提供されているActionsを読み込んで使うことが難しい 割と大胆なActionsを書いてくる(Azure CLIとかGitHub CLIを使うような) 回避策: GitHub Actionsはプログラム言語レベルで多岐にわたらないため、Vibe Codingではなく、人力コーディングで行ったほうが良いという結論になりました。 まとめ 今回は、Claude Code使用時の「Vibe Coding」から脱却するための実践的なTipsをまとめてみました。 重要なポイントをまとめると: 事前のドキュメント化と設計書作成を徹底する セッション管理とタスクサイズの適正化 ファイル種別による特性を理解して使い分ける 型の不整合やスコープの明確化に注意する Claude Codeは非常に強力なツールですが、適切な使い方を身につけることで、その真価を発揮できるようになります。皆さんも、ぜひこれらのTipsを参考に、より効率的な開発フローを構築してみてください! LinterとFormatterの設定など、基本的な開発環境の整備も忘れずに。ここは人間と一緒ですからね。 Claude Codeでの開発、一緒に極めていきましょう! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 「適当にプロンプト投げるだけ」を卒業!Vibe Coding脱却術:【Claude Code】 first appeared on SIOS Tech. Lab .
アバター
はじめに みなさん、こんばんは。最近はClaude CodeでAIにコードを書かせる検証をしている龍ちゃんです。 先月はあまりブログを書けなくて、僕もビックリするぐらい三本しか書いていませんでした。今月は多少時間を取ってでもブログを書いていこうと思っています。 まず Vibe Codingをやってみて感じた課題感 に関してはこちらでまとめています。 AIが悪いのではなく、人間が悪い 色々検証して思ったことですが、 だいたい人間の入力が悪い というか、人間のせいなんですよね。AIの仕組みでそれを解消しようという試みもありますが、業務でAIを使うなら、人間の入力が悪いと考えて、入力の方を改善していく方が、AIの精度向上を待つよりも効果的だと思います。人間の入力をいかに変えていくかということにフォーカスを当てて検証を進めています。つまり、 Claude Codeが悪いんじゃなく、人間が悪い んです。 人間の入力をAIが理解しやすいように作っていくという前提を押さえてもらえればと思います。 従来手法の限界:ペアコーディング 最初の1〜2ヶ月間、Claude Codeを使い始めた頃は、Vibe Coding(ペアコーディング)という手法で開発していました。プロンプトとしては100から300文字ぐらいのシンプルなものを投げていました。 これだと小規模な改善や機能追加には非常に優秀でした。リファクタリングも効果的でした。しかし、大規模な開発(例えば、一つのページ全体を組むような)をしようとすると、意図したとおりのものを作ってくれないことがありました。AIが自由に解釈しすぎて、変なものを作ってくることもありました。 ペアコーディングの具体的な問題点 実際にペアコーディング手法で開発していて気づいた課題があります。雑なプロンプトを投げて作ったものだと、やっぱり意図したものが作られないということが頻繁にありました。また、ペアプログラミング的な使い方だと人間の手が入る分、作業が遅くなるという印象もありますね。 特に既存プロジェクトで、すでにコード規約やディレクトリ構成が決まっている状態なら、それを学習させてからエンドポイントを追加する作業は割と有効だと思います。しかし、 300文字程度で自分が作りたいものを説明するのは文豪でも難しいでしょう 。文章が苦手な人にとっては尚更です。 ここで思い出してほしいのが「人間が悪い」ということです。そういう意味では、「意図したものができない」と言っている人は、当然のことを言っているだけなのです。 このような背景があり、リファクタリングは得意分野だと言えます。既存コードのパフォーマンス問題を改善するといった単純な指示は分かりやすいです。しかし新機能開発となると話が違います。Claude Codeで自分の意図したとおりのものを作る手法についてお話ししようと思います。 ディレクトリ構成とファイル管理 ディレクトリ構成としては、計画・検証用のドキュメント部分と実装コード部分を分けています。 / ├── CLAUDE.md # プロジェクト全体のガイドライン ├── docs/ # 計画・設計フェーズ │ ├── CLAUDE.md # 計画フェーズ専用ルール │ ├── features/ # 新機能計画 │ ├── bugs/ # バグ調査・修正計画 │ └── research/ # 検証結果・知見 └── application/ # 実装フェーズ ├── backend/ │ └── CLAUDE.md # バックエンド実装ルール └── frontend/   └── CLAUDE.md # フロントエンド実装ルール 新手法:3フェーズ開発 最近実践している方法では、開発フェーズを「 計画 」「 実装 」「 検証 」の3つに分けています。 計画フェーズ まず「計画」フェーズでは、やりたいことの仕様書をAIに説明し、文書化してもらいます。 このフェーズではコードを一切書かせません (型定義などの簡単なものは除く)。 AIが返してきたドキュメントを確認し、自分の意図しているものかを確認します。これによってAIが自由に解釈する余地を減らします。 計画フェーズで効果を発揮するCLAUDE.mdや具体的な手法・効果については「 AI協働で仕様書アレルギー克服!開発時間を1週間→2日に短縮する実践法 」で紹介しています。 実装フェーズ 次に「実装」フェーズでは、作成した仕様書を読み込ませ、それに基づいて実装してもらいます。説明は全て計画フェーズで作った仕様書に含まれているので、それを入力として与えるだけです。 人間は監視役に徹し、AIが暴走した場合は適宜小さなプロンプトで修正します。 龍ちゃん 実装時に陥りそうな課題に関しては、「 Claude Code仕様書ベースでハマる6つの落とし穴!失敗回避の備忘録 」でも書いています。 検証フェーズ 最後の「検証」フェーズでは、仕様書の不備がどこにあったか、その結果どのような変更が加えられたかを分析します。これにより実装と仕様を照らし合わせ、根拠のない編集を防止できます。実装後は人間の手で確認作業を行います。 計画と実装を比較することで、レビューした仕様書の中で不足があった分などを特定することができます。 計画ドキュメントと実装の内容を確認して、計画と実装の差異がある点をまとめてください。 ここで不測の指摘があるってことは、仕様書や計画が不足しているということになります。ここで学びができますね。 実際の開発効果:驚異的な時間短縮 この3フェーズ手法を実践してみて、開発期間は圧倒的に短縮されました。具体的な事例をご紹介しますと: 小規模システムの例 バックエンドのエンドポイント2つ フロントエンドの画面1つ 開発時間:約30分で完了 作った画面は結構シンプルなシステムでしたが、エンドポイントの仕様としては単純なものでした。この規模なら、仕様書作成から実装まで含めて30分という短時間で完成します。 中規模システムでの限界 一方で、バックエンドのエンドポイントが4つで、フロントエンドの画面でそれら4つのエンドポイントをいい感じに使うような中規模なものを作ろうとすると、セッションが限界になったりということがありました。この辺はタスクを分割するべきだったなと考えています。 この手法の効果と学び、そして課題 現在はプライベートリポジトリで検証しているため、大規模プロジェクトへの導入経験はまだありませんが、中規模程度の開発であれば強力なツールになると思います。特に プロトタイピングでは大きな力を発揮しそう です。 バグ発生率と仕様漏れの実態 開発時の課題として、バグというよりも 仕様漏れ の方が圧倒的に多いです。仕様書を元に開発するので、仕様から漏れている内容が実装している最中やテストしている最中に気づいたりします。これは大体バグというより仕様漏れかなと思います。 ビルドが失敗するようなケースは結構あるんですが、PrettierやESLintなどのフォーマッターやリンターをちゃんと定義しておいて、その定義の下で処理してもらうようにするとある程度コードとしては綺麗になります。 ただし、ディレクトリ構成やプロジェクトのコード設計思想みたいなところを伝えていないと、fat controllerのように1ファイルに対して過剰にコードを書いてしまうみたいなことは割とありがちですね。 学習効果の発見 個人的に学びになった点としては、仕様書作成が苦手な私でも、AIが返してきた仕様書を見て「分かりやすい」と感じることがあります。学習的な側面でも価値があると思います。 完璧な仕様書があれば理想的ですが、そういうものは実際には存在せず、どこかに不備があるものです。だからこそ、 機能ごとに段階的に仕様書を作っていくアプローチが有効 だと思います。 また、検証フェーズで計画の不備を見つけるプロセスを踏むことでレビュー観点を育てることができます。レビューをする体験そのものが貴重です。 実践での注意点とコツ ここにまとまり切っていない部分に関しては別途「 Claude Code仕様書ベースでハマる6つの落とし穴!失敗回避の備忘録 」でまとめています。 この手法が向いていない作業 実際に検証してみて、 この3フェーズ手法でも上手くいかない作業 があることが分かりました。 プロジェクト構造の大幅変更 プロジェクトのディレクトリ構成を変えるような作業は、Claude Codeだとパスの解決なども自動でやってくれるのですが、使っている・参照しているファイルを再帰的に検索してということになるので、実際時間がかかってしまうという印象があります。 簡単なリネーム作業 関数のリネームのような作業に関しては、人間の手作業の方が圧倒的に早いです。VS Codeのリファクタリング機能のようなサポート機能を使うのがいいんじゃないかなと思っています。 フロントエンドデザインの特殊性 フロントエンドのデザインに関しては、仕様書を書いて作るというのはあまり向いていない かなと思ってます。 理由としては: フロントエンドで最初に想定していた仕様が全てを満たすことって無い UIを文章で説明するのって結構な分量が必要 分量が増えるとAIが混乱する確率も上がる 実際に画面を見て「何か違うな」という瞬間が割とある 自分の書いている仕様と自分の頭の中にあるイメージが合ってることがあまりない コンテキストが膨大に増えていく そのため、フロントエンドに関しては別のアプローチが必要だと考えており、別途検証を進めています。 Claude Codeの”忘れっぽさ”との付き合い方 実際に運用していて気づいたのですが、 CLAUDE.mdにいくら設定を書いても、コンテキストを無視することが結構あります 。特に長時間の作業や複雑なタスクになると、最初に設定した原則を忘れてしまうことがありますね。 そういう時の対処法として、私は以下のようなアプローチを取っています: リアルタイム修正パターン 動作を確認しながら進めて、「あ、意図した挙動をしてないな」と感じた瞬間に処理を止めます。そして、プロンプトに守ってほしい原則を改めて追加して再度実行する、という感じですね。 事後確認パターン 処理が完了した後に、「あれ?原則守ってないですよね?」とClaude Codeに詰める作業も行っています。これによって、なぜその判断をしたのかを確認し、次回の改善につなげています。 この経験から学んだのは、 AIも完璧ではない ということです。「人間が悪い」と言いましたが、同時にAI側の限界も理解して、適切にガードレールを設ける必要がありますね。完璧な仕様書があれば理想的ですが、そういうものは実際には存在しないのと同じように、完璧なAIも存在しません。だからこそ、人間とAIの協働において、お互いの特性を理解することが重要だと感じています。 適用に向いているプロジェクト 逆に、この手法が効果的なのは: バックエンドのAPI開発 :仕様が明確に定義しやすい データ処理ロジック :入力と出力が明確 既存プロジェクトへの機能追加 :コード規約やディレクトリ構成が既に決まっている プロトタイピング :完璧性よりもスピードを重視 まとめ 私は新機能開発とバグレポートをこの二つの方法で分けて対応しています。計画段階で仕様書を挟むことで、意図したものを作れるようになります。 ただし、万能ではありません。プロジェクトの性質や作業内容によって、従来のペアコーディング手法や人間による手作業の方が効率的な場合もあります。 適材適所で使い分けることが重要 ですね。 皆さんも、ぜひこの3フェーズ開発手法を試してみて、自分のプロジェクトに合うかどうか検証してみてください!何か質問や改善点があれば、コメントでお聞かせください。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Code革命!3フェーズ開発で効率的な開発:計画→実装→検証術 first appeared on SIOS Tech. Lab .
アバター
はじめに ども!最近はGitHubをCMSとして活用する検証にハマっている龍ちゃんです。社内システムでGitHubをCMSとして使ったデータ管理を2パターン試してみたんですが、それぞれ全然違う特性で面白かったんですよね。 「GitHubをCMSとして使いたいけど、どうやってデータを取得するのがベストなんだろう?」って悩んでいる方、結構多いんじゃないでしょうか? 今回は、私が実際に検証した2つのアプローチを比較します: ランタイムAPIアクセス (NestJS + GitHub API) ビルドタイム同期 (GitHub Actions外部リポジトリ統合) どちらも実際にプロダクション環境で運用してみたので、リアルな運用データと合わせて比較していきますね! 2つのアプローチ概要 ランタイムAPIアクセス(NestJS実装) 特徴: リクエスト時にリアルタイムでGitHub APIを呼び出し 常に最新のデータを取得 サーバーサイドでAPI呼び出しを実行 ビルドタイム同期(GitHub Actions) 特徴: 事前にデータをビルド時に同期 静的ファイルとして配信 定期実行やトリガー実行での更新 技術的詳細比較 アーキテクチャの違い 項目 ランタイムAPIアクセス ビルドタイム同期 データ取得タイミング ユーザーリクエスト時 ビルド/デプロイ時 データ鮮度 リアルタイム 同期タイミング次第 サーバー負荷 API呼び出し毎回 静的配信 障害耐性 GitHub API依存 静的ファイル レスポンス速度 API待機時間あり 即座にレスポンス 運用面での比較 ランタイムAPIアクセス メリット デメリット デバッグが容易(ログでAPI呼び出しを追跡可能) レート制限対策が必要 即座にデータ反映 GitHub API障害の影響を直接受ける シンプルなエラーハンドリング サーバー監視が必須 API呼び出しによる遅延が発生 継続的なサーバーリソース消費 ビルドタイム同期 メリット デメリット 本番環境が安定(静的配信) データ反映にタイムラグあり GitHub API障害の影響を受けにくい GitHub Actions失敗時の対処が必要 運用コストが低い デバッグが間接的 高速なレスポンス 同期処理の複雑性 CDN活用による配信最適化 データ整合性の管理が困難 用途別推奨パターン ランタイムAPIアクセスを選ぶべきケース 推奨条件: - データ更新頻度: 高頻度(1日数回以上) - ユーザー数: 小〜中規模(同時接続 < 100) - 予算: サーバー運用費用が確保可能 - リアルタイム性: 重要 具体例: - 社内ドキュメントシステム - 個人ブログ(更新頻度高) - プロトタイプ・MVP開発 - チーム内情報共有ツール ビルドタイム同期を選ぶべきケース 推奨条件: - データ更新頻度: 低〜中頻度(1日数回以下) - ユーザー数: 大規模対応が必要 - 予算: 運用コスト削減重視 - パフォーマンス: 高速レスポンス必須 具体例: - 企業サイト・LP - 技術ブログ - ドキュメントサイト - ニュースサイト(定期更新) ビルドタイム同期のポイント: セキュアなPAT管理とアクセス制御 データ整合性チェックとバリデーション エラー時のフォールバック機構 ハイブリッド構成という第3の選択肢 実際の運用では、2つのアプローチを使い分ける選択肢もあります: 適用パターン 静的コンテンツ : ビルド時同期(ドキュメント、記事等) 動的コンテンツ : ランタイムAPI(ユーザー投稿、リアルタイム情報等) 頻度別管理 : 更新頻度に応じた自動振り分け ハイブリッド構成の特性比較 メリット デメリット 各コンテンツの特性に最適化 システム複雑性の増加 コストとパフォーマンスの両立 運用・監視コストの増大 段階的な移行が可能 デバッグ・障害対応の難易度上昇 リスク分散効果 技術スタックの多様化によるスキル要求 推奨判断基準 ハイブリッド構成を検討すべきケース: ├─ コンテンツ種別が明確に分かれている ├─ 段階的移行でリスク軽減したい ├─ 運用チームに十分なスキルがある └─ システム複雑性を許容できる予算・体制 セキュリティ面での考慮 項目 ランタイムAPI ビルドタイム PAT管理 本番サーバーに保存 CI/CD環境のみ アクセス制御 サーバーサイド制御 静的ファイル権限 ログ監査 詳細なアクセスログ ビルドログのみ 障害影響範囲 即座にサービス影響 既存データで継続 まとめ:最適解の選び方 決定フローチャート データ更新頻度は? ├─ 高頻度(1日数回以上) │ └─ ユーザー数は? │ ├─ 小規模(<100) → ランタイムAPI │ └─ 大規模(>100) → ハイブリッド構成 │ └─ 低頻度(1日数回以下) └─ コスト重視? ├─ Yes → ビルドタイム同期 └─ No → どちらでも可 技術選択の判断基準(検証結果) ランタイムAPI適用ケース: 小規模チームでの情報共有システム プロトタイプ開発(迅速なデバッグ重視) リアルタイム性が重要な管理画面 ビルドタイム同期適用ケース: 技術ブログやドキュメントサイト アクセス数が多い企業サイト 安定性を重視するシステム 今後の展望 GitHub APIエコシステムは進化し続けています: GitHub Apps認証 の活用でセキュリティ強化 GraphQL API による効率的なデータ取得 Webhook との連携でリアルタイム同期 どちらのアプローチを選んでも、これらの新機能を活用することで、さらに強力なシステムが構築できるでしょう。 次のステップ この記事を読んで「実際に試してみたい!」と思った方は、まずは小さなプロトタイプから始めることをおすすめします。GitHubの無料枠とActions無料枠を使えば、コストをかけずに両方のアプローチを検証できますよ! 皆さんも、ぜひ自分のプロジェクトに合った方法でGitHubをCMSとして活用してみてください。質問やご相談があれば、いつでもお声がけくださいね! 参考資料 GitHub REST API Documentation GitHub Actions Documentation NestJS GitHub Integration Best Practices Personal Access Token Security Guidelines ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post GitHub CMS実装:ランタイム vs ビルドタイム比較!用途別プラクティス first appeared on SIOS Tech. Lab .
アバター
初めに 最近は社内の活動を少しでもやりやすくするための社内システム開発を龍ちゃんです。合わせて、AIと協業して開発する検証も進めています。AIを開発に入れてから、少ない人数で開発を回せているので素晴らしいですね。今回は、AIとはちょっと関係ない領域でのコンテンツですけど… 今回は、GitHubの優れた編集・レビュー機能をそのまま活用しながら、APIで簡単に自分のシステムに組み込む方法を紹介します。 なぜGitHubをCMSとして使うのか? 最大の魅力:GitHubの機能をフル活用できる 編集 : VS Codeライクなエディタで快適に編集 レビュー : Pull Requestで複数人でのレビュー 履歴管理 : すべての変更履歴が自動保存 検索 : リポジトリ内の強力な検索機能 権限管理 : チームでの細かいアクセス制御 つまり、 コンテンツの作成・編集・管理はGitHubに任せて、自分のシステムは「読み取り」に専念できる のです。 こんな使い方ができる GitHubリポジトリ構成例: /posts ├── 2024-01-15-github-api-guide.md ├── 2024-01-20-nestjs-tips.md └── 2024-01-25-typescript-tricks.md → これをAPIで取得して、ブログや社内ドキュメントサイトに表示! こちらのシステムと統合して使用する ことで、GitHub上で作成した成果物ををシステムに統合することができます。 Personal Access Token (PAT) の設定 GitHub APIを使うためには、PATの設定が必要です。 基本設定(検証で使いまわししたい場合) GitHub Settings → Developer settings → Personal access tokens → Tokens (classic) Generate new token をクリック 権限は repo を選択(プライベートリポジトリアクセス用) セキュリティ重視の場合 Fine-grained PAT の使用を推奨します: 対象リポジトリを限定可能 必要な権限: Contents: Read のみでOK 有効期限の強制設定でより安全 レート制限が劇的に改善されるんです! PAT認証の違いは劇的 なんですよ。 認証方式 1時間あたりの制限 1分あたり換算 認証なし 60回 1回/分 PAT認証 5,000回 83回/分 *つまり、PATを使うだけで83倍のリクエストが可能になるんです!**これは使わない手はないですよね。 コピペで動く!NestJSコントローラー実装 環境変数を設定 GITHUB_OWNER=your-username GITHUB_REPO=your-repo-name GITHUB_TARGET_DIRECTORY=/posts GITHUB_PAT=ghp_xxxxxxxxxxxxxxxxxxxx コントローラーにコピペするだけ! import { Controller, Get, Param, HttpException, HttpStatus } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; @ApiTags('GitHub CMS') @Controller('api/github-cms') export class GitHubCmsController { private readonly baseUrl = 'https://api.github.com'; private readonly githubPat = '取得したPATを埋め込んでね!'; private readonly githubOwner = 'リポジトリOwnerを入れてね'; private readonly githubRepo = 'リポジトリ名を入れてね!'; private readonly githubTargetDirectory = '/posts'; private async githubRequest(path: string): Promise<any> { const response = await fetch(`${this.baseUrl}${path}`, { headers: { 'Authorization': `Bearer ${this.githubPat}`, 'Accept': 'application/vnd.github+json', 'User-Agent': 'github-cms-client/1.0' } }); if (!response.ok) { const errorMessages = { 401: 'GitHub認証エラー: PATを確認してください', 403: 'アクセス権限がありません', 404: 'リソースが見つかりません', 429: 'レート制限に達しました' }; throw new HttpException( errorMessages[response.status] || `GitHub API Error: ${response.status}`, response.status ); } return response.json(); } @Get('files') @ApiOperation({ summary: 'Markdownファイル一覧を取得' }) @ApiResponse({ status: 200, description: 'ファイル一覧' }) async getFiles() { const path = `/repos/${this.githubOwner}/${this.githubRepo}/contents${this.githubTargetDirectory}`; const files = await this.githubRequest(path); const markdownFiles = files.filter((file: any) => file.type === 'file' && file.name.endsWith('.md') ); return markdownFiles.map((file: any) => ({ name: file.name, path: file.path, sha: file.sha, size: file.size, downloadUrl: file.download_url })); } @Get('files/:filename') @ApiOperation({ summary: '特定のMarkdownファイルの内容を取得' }) @ApiResponse({ status: 200, description: 'ファイル内容' }) @ApiResponse({ status: 404, description: 'ファイルが見つかりません' }) async getFileContent(@Param('filename') filename: string) { if (!filename.endsWith('.md')) { filename += '.md'; } const path = `/repos/${this.githubOwner}/${this.githubRepo}/contents${this.githubTargetDirectory}/${filename}`; try { const file = await this.githubRequest(path); const content = Buffer.from(file.content, 'base64').toString('utf-8'); return { name: file.name, path: file.path, content: content, sha: file.sha, size: file.size, downloadUrl: file.download_url, htmlUrl: file.html_url }; } catch (error) { if (error.status === 404) { throw new HttpException('ファイルが見つかりません', HttpStatus.NOT_FOUND); } throw error; } } @Get('rate-limit') @ApiOperation({ summary: 'GitHub APIレート制限情報を取得' }) @ApiResponse({ status: 200, description: 'レート制限情報' }) async getRateLimit() { const data = await this.githubRequest('/rate_limit'); return { limit: data.rate.limit, remaining: data.rate.remaining, resetAt: new Date(data.rate.reset * 1000), used: data.rate.limit - data.rate.remaining }; } } 使い方はこんな感じ! APIエンドポイント # ファイル一覧を取得 GET /api/github-cms/files # 特定のファイル内容を取得 GET /api/github-cms/files/2024-01-15-github-api-guide.md # レート制限を確認 GET /api/github-cms/rate-limit レスポンス例 // GET /api/github-cms/files [ { "name": "2024-01-15-github-api-guide.md", "path": "posts/2024-01-15-github-api-guide.md", "sha": "abc123...", "size": 2048, "downloadUrl": "https://raw.githubusercontent.com/..." }, // ... ] // GET /api/github-cms/files/2024-01-15-github-api-guide.md { "name": "2024-01-15-github-api-guide.md", "path": "posts/2024-01-15-github-api-guide.md", "content": "# GitHub API活用ガイド\\n\\n本文...", "sha": "abc123...", "size": 2048, "downloadUrl": "https://raw.githubusercontent.com/...", "htmlUrl": "https://github.com/..." } フロントエンドでの使用例 // React/Next.jsでの実装 import { useEffect, useState } from 'react'; export default function BlogList() { const [posts, setPosts] = useState([]); useEffect(() => { fetch('/api/github-cms/files') .then(res => res.json()) .then(data => setPosts(data)); }, []); return ( <div> <h1>ブログ記事一覧</h1> {posts.map(post => ( <div key={post.sha}> <Link href={`/blog/${post.name.replace('.md', '')}`}> {post.name.replace('.md', '')} </Link> </div> ))} </div> ); } まとめ GitHubをCMSとして使うメリット: 編集・レビュー機能が無料で使える – GitHubの優れたUIをそのまま活用 APIアクセスが簡単 – シンプルな実装で十分実用的 レート制限もPATで解決 – 83倍のリクエストが可能に バージョン管理付き – すべての変更履歴が自動保存 つまり、 コンテンツ管理の面倒な部分はGitHubに任せて、自分はAPIで読み取るだけ という理想的な構成が実現できます。 こんなプロジェクトにおすすめ 個人ブログ・技術ブログ 社内ドキュメントサイト 静的サイトのコンテンツ管理 チームで編集する設定ファイル管理 GitHubの編集・レビュー機能を活用しながら、APIで簡単に自分のシステムに組み込める。これが「GitHub as a CMS」の魅力です! 参考資料 GitHub公式ドキュメント GitHub REST API Documentation – APIの完全なリファレンス Rate limits for the REST API – レート制限の詳細(認証なし60回/時 vs PAT認証5,000回/時の比較表あり) Contents API – ファイル取得APIの仕様 Personal Access Token (PAT) について Creating a personal access token – PATの作成手順 Scopes for OAuth apps – 必要な権限スコープの説明 実装に役立つリソース Octokit.js – GitHub公式のJavaScript SDKもあります(今回は使わずにfetch APIで実装) gray-matter – Markdown Frontmatterのパース用ライブラリ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post GitHubをCMSに!NestJSでAPI実装する実践方法【コード付き】 first appeared on SIOS Tech. Lab .
アバター
はじめに ども!最近はXの自動投稿システムにハマっている龍ちゃんです。開発の方はかなりいい感じで進んでほくほく顔ですね。 皆さんも複数のリポジトリでデータ連携する時って、「どうやって安全に取り込もうか?」って悩むことありませんか?今回は、そんな課題を解決するGitHub Actionsを使った外部リポジトリ統合手法について、実際のプロダクション環境で検証した内容をシェアします。 活用シナリオ この手法が特に威力を発揮するのは、以下のようなケースです: コンテンツ管理の分離 :ブログポストを別リポジトリで管理し、開発者とコンテンツ作成者で作業領域を分ける 設定ファイルの共有 :複数のアプリケーション間で設定やデータを一元管理 権限管理 :コンテンツとアプリケーションで異なるアクセス権限を設定 私の具体的なケースでは、 Xの投稿文を自動で作成してプルリクエストを生成するシステム を別途構築し、そのデータをメインアプリケーションに取り込む必要がありました。 Personal Access Token (PAT) の設定 GitHub APIを使うためには、PATの設定が必要です。 基本設定(検証で使いまわししたい場合) GitHub Settings → Developer settings → Personal access tokens → Tokens (classic) Generate new token をクリック 権限は repo を選択(プライベートリポジトリアクセス用) セキュリティ重視の場合 Fine-grained PAT の使用を推奨します: 対象リポジトリを限定可能 必要な権限: Contents: Read のみでOK 有効期限の強制設定でより安全 リポジトリシークレットと環境変数の設定 作成したPATをGitHubリポジトリのSecretsに登録します: リポジトリの Settings > Secrets and variables > Actions New repository secret をクリック 名前: GHCR_TOKEN 、値:作成したPATを入力 続いて、リポジトリの Variables タブで以下を設定: EXTERNAL_REPO_OWNER : 外部リポジトリの所有者 EXTERNAL_REPO_NAME : 外部リポジトリ名 重要な注意点 :シークレット名に GITHUB_TOKEN は使用できません。これはGitHubが予約している名前のため、エラーになります。今回は GHCR_TOKEN としましたが、 EXTERNAL_REPO_TOKEN など分かりやすい名前を付けましょう。 環境変数として分けることで設定の柔軟性とメンテナンス性が大幅に向上します。後からリポジトリ名が変わっても、ワークフローファイル自体を変更する必要がありません。 実装詳細 ワークフロー全体構成 まずは全体の構成から見てみましょう: name: Sync External Data on: workflow_dispatch: permissions: contents: read actions: read env: EXTERNAL_REPO_OWNER: ${{ vars.EXTERNAL_REPO_OWNER || '' }} EXTERNAL_REPO_NAME: ${{ vars.EXTERNAL_REPO_NAME || '' }} 実装のポイント解説: workflow_dispatch で手動実行を可能に 環境変数で外部リポジトリ情報を管理 contents: read のみでOK:ファイル操作はローカルで完結し、リポジトリへのcommitは行わないため 私の検証環境では、最初permissions設定を忘れて「なんで動かないんだ?」ってハマりました。あと、会社側のリポジトリへのアクセス権を振ってないなんてこともありましたね。皆さんはこの辺り、気をつけてくださいね。 外部リポジトリの取得 - name: Step 1 - Fetch external repository if: ${{ env.EXTERNAL_REPO_OWNER != '' && env.EXTERNAL_REPO_NAME != '' }} uses: actions/checkout@v4 with: repository: ${{ env.EXTERNAL_REPO_OWNER }}/${{ env.EXTERNAL_REPO_NAME }} token: ${{ secrets.GHCR_TOKEN }} path: external-repo fetch-depth: 1 # 最新コミットのみ取得してパフォーマンス向上 重要な設定解説: token: ${{ secrets.GHCR_TOKEN }} : PAT認証を使用 path: external-repo : 取得先ディレクトリを指定 fetch-depth: 1 : 履歴を取得せず最新のみでパフォーマンス向上 if 条件で環境変数の存在をチェック ダミーデータのクリーンアップと差し替え - name: Step 2 - Clear existing markdown files run: | echo "Removing existing markdown files..." rm -f ./application/frontend/markdown/*.md echo "Existing markdown files removed" - name: Step 3 - Copy posts directory if: ${{ env.EXTERNAL_REPO_OWNER != '' && env.EXTERNAL_REPO_NAME != '' }} run: | echo "Copying posts directory from external repository..." if [ -d "./external-repo/posts" ]; then cp -r ./external-repo/posts/* ./application/frontend/markdown/ echo "Posts directory copied successfully" echo "Final markdown directory contents:" ls -la ./application/frontend/markdown/ else echo "Posts directory not found in external repository" exit 1 fi この処理では、開発中はダミーデータでアプリ側の挙動を確認し、デプロイする際に本番データに差し替えています。これによって、ダミーデータで動作確認しながら開発ができて、本番時は本当のデータでアプリを動かすことができるんです。 セキュリティと運用上の注意点 トークンの適切な管理 セキュリティ面での注意点について、実際の運用で学んだポイントをシェアします: 最小権限の原則 :必要最小限のスコープのみを付与 定期的なトークンのローテーション :90日推奨 環境別の設定 :本番環境とテスト環境でトークンを分離 更新管理の対策 この構成における運用上の重要な注意点として、 GitHub Actionsを実行した時にのみデータが更新される 点があります。外部リポジトリに変更を加えた場合、以下のような対策が有効です: スケジュール実行による定期的な同期 on: schedule: - cron: '0 6 * * *' # 毎日6時に実行 CI/CDパイプラインの一部として組み込む デプロイ前の必須ステップとして設定 本番データ同期の自動化 実際に運用してみると、「あれ?データが古いままだ」ってことがよくあります。この辺りの仕組みをしっかり作っておくと、運用が格段に楽になりますよ。 よくあるトラブルと対処法 実際に運用していて遭遇したトラブルと対処法をまとめました: PAT権限不足エラー(403 Forbidden) :PAT作成時に必要な権限スコープを再確認 ファイルが見つからないエラー : ls -la コマンドでディレクトリ構造を確認 環境変数未設定エラー :Repository Variablesの設定を確認 まとめ PATを使用したGitHub Actions外部リポジトリ統合により、以下を実現できます: セキュアなアクセス制御 :適切な権限管理で安全性を確保 柔軟な運用 :環境変数による設定の外部化でメンテナンス性向上 自動化されたワークフロー :手動作業を削減し、ヒューマンエラーを防止 データ整合性の保証 :バリデーションと復旧機能で信頼性向上 実装時は、セキュリティ、パフォーマンス、保守性の観点から十分な検討を行い、チームの開発フローに適合した形で導入することが重要です。特にPATの管理については、定期的なローテーションと最小権限の原則を徹底しましょう。 皆さんも、ぜひこの手法を使って効率的なデータ連携にチャレンジしてみてください!質問やご相談があれば、いつでもお声がけくださいね。 参考リンク GitHub Actions Checkout Action GitHub Personal Access Tokens 管理ガイド GitHub Actions Secrets 使用ガイド ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post GitHub Actions×PATで実現!セキュアな外部リポジトリ統合の実践手法 first appeared on SIOS Tech. Lab .
アバター
はじめに ども!最近はClaude Codeにべったりな龍ちゃんです。皆さんは技術ブログから SNS 投稿まで、コンテンツマーケティングの自動化に取り組んでいますか?エンジニアやっている傍らで、情報発信やXの運用なども行っています。 私たちのチームでも以前、 Claude のプロジェクト機能でブログから X 投稿文を自動生成するシステム を構築しました。これはこれで便利だったのですが、運用していくうちに以下の課題が明らかになったんですね。 Claude プロジェクトの運用課題 Claude の契約者しか利用できず、チーム内での共有や協業に制限がある システムプロンプトの更新が上書き保存となり、改善履歴や変更効果の追跡ができない 成果物が Claude 上や他ツールに分散し、管理とレビューワークフローが属人化しやすい 「これは何とかしないと…」ということで、Claude API × GitHub Actions による完全自動化システムを構築することにしました。今回は設計思想から実装のポイント、コスト最適化まで詳しく解説していきますね。 成果物 今回の作成物は、.envファイルにClaude APIのAPI Keyを環境変数として入れることで動作するようになります。興味がある方はリポジトリを読んでみてください。こちらのリポジトリではPythonを書く環境をDevContainerで構築しています。 参考 GitHub – Ryunosuke-Tanaka-sti/github-x-generate-demo GitHub GitHub × Claude API で実現する解決アプローチ 基本コンセプト 「GitHub だけでブログ URL から X 投稿文の生成・レビュー・公開まで完結」を目指しました。具体的には以下を実現しています: ワンクリック起動 : URL 入力で自動実行 完全なバージョン管理 : Git でプロンプト・成果物を管理 チーム協業 : 誰でもレビュー・承認可能 コスト最適化 : API 利用料を最小化 システム全体の流れ 自動化フローは以下のようになります: GitHub Issue でトリガー : 記事 URL をタイトルに入力してイシューを作成 HTML 自動取得 : Python スクリプトで記事本文を抽出・クリーニング Claude API で分析 : プロンプトキャッシュを活用して 3 パターンの投稿文を生成 PR 自動作成 : 生成結果を含む Pull Request を自動作成 レビュー・マージ : チームメンバーが内容を確認して承認 このフローにより、Issue 作成から最終的な投稿文完成まで、すべて GitHub 上で完結できるようになりました。 コスト最適化の技術的工夫:API 利用料を 60% 削減 Claude API の利用において、最も大きなコスト要因はトークン数です。私たちは以下の 2 つのアプローチでコストを大幅に削減しました。 1. HTML 前処理によるトークン削減(約 50% 削減) 当初はブログページの HTML を丸ごと送信していましたが、よく考えてみれば記事本文のみが必要なんですよね。Python スクリプトで以下の前処理を実装しました: # 不要な HTML 要素の除去例 - ヘッダー・フッター・ナビゲーション - サイドバー・広告・関連記事 - JavaScript・CSS・meta タグ - コメント欄・SNS ボタン この前処理により入力トークン数を約 50% 削減、コストが半分になりました。 2. プロンプトキャッシュの活用(約 37% 削減) Claude API のプロンプトキャッシュ機能 を活用することで、システムプロンプト部分のトークン利用料を大幅に削減しました。 # プロンプトキャッシュの実装例 response = self.client.messages.create( model=self.model, max_tokens=4000, system=[ { "type": "text", "text": self.system_prompt_content, "cache_control": {"type": "ephemeral"} # キャッシュ設定 } ], messages=[{"role": "user", "content": user_prompt}] ) システムプロンプトをキャッシュすることで、2 回目以降は約 37% のコスト削減を実現しています。 実際のコスト削減効果 両方の最適化を組み合わせることで、実行コスト $0.10 → $0.04 程度に削減できました。年間で考えるとかなりの削減効果ですね。 システム実装の詳細 プロジェクト構成 github-x-generate/ ├── scripts/ # 実行スクリプト群 │ ├── generate_posts_with_cache.py # Claude API統合 │ ├── fetch_html_from_techlab.py # HTML取得・前処理 │ └── simple_claude_api.py # API クライアント ├── prompts/ │ └── system_prompt.md # システムプロンプト定義 ├── .github/workflows/ │ └── generate_PR_from_issue.yaml # メイン自動化ワークフロー ├── posts/ # 生成結果保存ディレクトリ └── requirements.txt # Python 依存関係定義 4 段階の投稿文生成プロセス システムプロンプトでは、以下の 4 段階プロセスで高品質な投稿文を生成します: Phase 1: 記事分析・品質評価 技術的正確性の 5 段階評価 実装レベルの判定(プロトタイプ〜企業レベル) 対象読者レベルの特定 Phase 2: ハッシュタグ効果分析 Web 検索による最新トレンドの調査 エンジニア向け効果的ハッシュタグの選定 Phase 3: 3 パターンの投稿文作成 A パターン: 効果重視・数値訴求型 B パターン: 課題共感・解決提案型 C パターン: 技術トレンド・学習促進型 Phase 4: 誇張表現検証・修正 記事内容との照合による事実確認 根拠のない数値・効果の除去 使用しているプロンプトはこちらのブログで解説をしています。 実際の運用フロー 1. GitHub Issue での起動 https://tech-lab.sios.jp/archives/48173 記事 URL をタイトルに入力して Issue を作成するだけで、GitHub Actions が自動起動します。これだけです! 2. 自動処理の実行 HTML 記事の取得と本文抽出(約 30 秒) Claude API による投稿文生成(約 45 秒) PR 作成とメタデータ保存(約 15 秒) トータル 1 分半程度で完了します。 3. レビュー・承認プロセス 生成された PR には以下が含まれます: 3 パターンの投稿文 : 異なるアプローチの投稿候補 品質評価データ : 技術的正確性や対象読者の分析結果 コスト情報 : 実際の API 利用料とトークン使用量 レビュアーは内容を確認し、必要に応じて微調整を加えてからマージするだけです。 4. 運用実績 23 件の技術記事で運用実績があり、Azure・インフラ、AI・Claude、Git・CI/CD、Docker・コンテナなど多様な技術分野で安定動作を確認しています。 効果とメリット 定量的な効果 コスト削減効果 HTML 前処理: 50% トークン削減 プロンプトキャッシュ: 37% トークン削減 総合的なコスト削減: 約 60% 工数削減効果 投稿文作成時間: 30 分 → 3 分(90% 削減) レビュー・修正工程: 20 分 → 5 分(75% 削減) 全体工程: 1 時間 → 10 分(83% 削減) 定性的なメリット チーム協業の向上 誰でも投稿文生成を実行可能 GitHub ベースのレビューワークフロー 知見の蓄積とバージョン管理 品質の向上 誇張表現の自動検出・修正 記事内容との整合性保証 3 パターンによるA/Bテスト可能 運用の効率化 Issue 作成からマージまで自動化 エラー時の詳細な診断情報 成果物の一元管理 これは想像以上に効果的でした。特に複数人でのコンテンツマーケティングには必須のツールになりそうですね。 まとめと今後の展望 Claude API × GitHub Actions により、個人プロジェクトでは困難だった「チーム協業」「バージョン管理」「コスト最適化」を同時実現することができました。約 60% のコスト削減と GitHub 完結型ワークフローにより、効率的な運用が可能になります。 今後の発展可能性 他プラットフォーム展開 : LinkedIn、Facebook 対応 多言語対応 : 英語版投稿文の自動生成 効果分析 : エンジニアリング指標の追加連携 統計分析活用 : 蓄積データによるプロンプト最適化 技術ブログのコンテンツマーケティング自動化にお悩みの方は、ぜひ参考にしてください。もし実装で困りごとがあれば連絡いただければお手伝いしますよ!! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude API×GitHub Actions完全自動化でコスト60%削減!ブログ投稿システム構築術 first appeared on SIOS Tech. Lab .
アバター