From 363e5f2d3d7e2fedbefeea376c4c4f4e4693cd0a Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Wed, 30 Jul 2025 17:30:40 +0900 Subject: [PATCH 01/21] feat: Add comprehensive CI/CD pipeline and deployment automation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add GitHub Actions workflow for multi-environment deployment (main/deploy branches) - Create interactive setup scripts for AWS IAM roles and OIDC configuration - create_role.sh: Bash script for Linux/macOS/Windows Git Bash - create_role.ps1: PowerShell script for Windows - Add environment-specific deployment scripts - deploy-env.sh: Local deployment for development/production - deploy-env.ps1: PowerShell version for local deployment - Configure SAM CLI for multi-environment deployment - samconfig.toml: Environment-specific deployment parameters - template.yaml: CloudFormation template with environment parameters - Add GitHub Secrets setup documentation (GITHUB_SECRETS_SETUP.md) - Configure Git attributes for cross-platform compatibility - Update requirements.txt and VS Code settings - Implement branch-based environment mapping: - main branch → production environment - deploy branch → development environment - Add robust tool detection and installation for AWS CLI, SAM CLI, GitHub CLI - Support multiple authentication methods (OIDC, SSO, access keys) - Fix SAM CLI detection to prioritize sam.cmd on Windows --- .gitattributes | 33 + .github/workflows/deploy.yml | 79 +++ .vscode/settings.json | 8 + GITHUB_SECRETS_SETUP.md | 122 ++++ create_role.ps1 | 1279 ++++++++++++++++++++++++++++++++++ create_role.sh | 1220 ++++++++++++++++++++++++++++++++ deploy-env.ps1 | 96 +++ deploy-env.sh | 77 ++ requirements.txt | 1 + samconfig.toml | 34 + template.yaml | 28 +- 11 files changed, 2970 insertions(+), 7 deletions(-) create mode 100644 .gitattributes create mode 100644 .github/workflows/deploy.yml create mode 100644 .vscode/settings.json create mode 100644 GITHUB_SECRETS_SETUP.md create mode 100644 create_role.ps1 create mode 100644 create_role.sh create mode 100644 deploy-env.ps1 create mode 100644 deploy-env.sh create mode 100644 samconfig.toml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4f3d655 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,33 @@ +# シェルスクリプトは常にLFを使用 +*.sh text eol=lf + +# PowerShellスクリプトは常にCRLFを使用 +*.ps1 text eol=crlf + +# その他のテキストファイル +*.txt text eol=lf +*.md text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.json text eol=lf +*.py text eol=lf +*.js text eol=lf +*.ts text eol=lf +*.html text eol=lf +*.css text eol=lf +*.xml text eol=lf + +# バイナリファイル +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.pdf binary +*.zip binary +*.tar binary +*.gz binary +*.exe binary +*.dll binary +*.so binary +*.dylib binary \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..12002d0 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,79 @@ +name: Deploy to AWS CloudFormation + +on: + push: + branches: + - main + - deploy + +env: + AWS_REGION: ap-northeast-1 + PROJECT_NAME: LambdaFramework + +permissions: + id-token: write + contents: read + +jobs: + deploy: + runs-on: ubuntu-latest + + # ブランチに基づいてデプロイ設定を決定 + strategy: + matrix: + branch: [main, deploy] + include: + - branch: main + stack_name: lambda-framework-prod + s3_bucket: cn-seba-aws-sam-cli-managed-default-samclisourcebucket + environment: production + aws_role_arn: ${{ secrets.AWS_ROLE_ARN_PROD }} + aws_region: ap-northeast-1 + - branch: deploy + stack_name: lambda-framework-dev + s3_bucket: cn-seba-aws-sam-cli-managed-default-samclisourcebucket + environment: development + aws_role_arn: ${{ secrets.AWS_ROLE_ARN_DEV }} + aws_region: ap-northeast-1 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Validate SAM template + run: | + sam validate + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ matrix.aws_role_arn }} + aws-region: ${{ matrix.aws_region }} + + - name: Deploy with SAM + run: | + sam build + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset \ + --stack-name ${{ matrix.stack_name }} \ + --s3-bucket ${{ matrix.s3_bucket }} \ + --parameter-overrides ProjectName=${{ env.PROJECT_NAME }} Environment=${{ matrix.environment }} + env: + SAM_CLI_TELEMETRY: 0 + + - name: Deploy status + if: always() + run: | + echo "Deployment completed for branch: ${{ github.ref }}" + echo "Stack name: ${{ matrix.stack_name }}" + echo "Environment: ${{ matrix.environment }}" + echo "Commit: ${{ github.sha }}" \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..22d1d12 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "cfn-lint.executablePath": "cfn-lint", + "cfn-lint.enable": true, + "yaml.validate": true, + "yaml.schemas": { + "https://raw.githubusercontent.com/aws/aws-sam-cli/master/samcli/local/schema/schema.json": "template.yaml" + } +} \ No newline at end of file diff --git a/GITHUB_SECRETS_SETUP.md b/GITHUB_SECRETS_SETUP.md new file mode 100644 index 0000000..0a993bb --- /dev/null +++ b/GITHUB_SECRETS_SETUP.md @@ -0,0 +1,122 @@ +# GitHub Secrets設定ガイド + +## 必要なGitHub Secrets + +### 開発環境用 +- **`AWS_ROLE_ARN_DEV`**: 開発環境用のIAMロールARN + - 例: `arn:aws:iam::123456789012:role/LambdaFramework-github-actions-role-dev` + +### 本番環境用 +- **`AWS_ROLE_ARN_PROD`**: 本番環境用のIAMロールARN + - 例: `arn:aws:iam::987654321098:role/LambdaFramework-github-actions-role-prod` + +## 設定手順 + +### 1. GitHub Secretsの設定 + +1. GitHubリポジトリの **Settings** → **Secrets and variables** → **Actions** に移動 +2. **New repository secret** をクリック +3. 以下のSecretsを追加: + +``` +Name: AWS_ROLE_ARN_DEV +Value: arn:aws:iam:::role/ + +Name: AWS_ROLE_ARN_PROD +Value: arn:aws:iam:::role/ +``` + +### 2. IAMロールの作成 + +各AWSアカウントで以下のIAMロールを作成: + +#### 開発環境用IAMロール +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "cloudformation:*", + "lambda:*", + "s3:*", + "iam:*", + "logs:*" + ], + "Resource": "*" + } + ] +} +``` + +#### 本番環境用IAMロール +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "cloudformation:*", + "lambda:*", + "s3:*", + "iam:*", + "logs:*" + ], + "Resource": "*" + } + ] +} +``` + +### 3. OIDCプロバイダーの設定 + +各AWSアカウントでGitHub Actions用のOIDCプロバイダーを設定: + +```bash +# 開発環境 +aws iam create-open-id-connect-provider \ + --url https://token.actions.githubusercontent.com \ + --client-id-list sts.amazonaws.com \ + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 + +# 本番環境 +aws iam create-open-id-connect-provider \ + --url https://token.actions.githubusercontent.com \ + --client-id-list sts.amazonaws.com \ + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 +``` + +## デプロイ先の確認 + +| ブランチ | AWSアカウント | スタック名 | 環境 | +|---------|-------------|-----------|------| +| `main` | 本番アカウント | `lambda-framework-prod` | production | +| `deploy` | 開発アカウント | `lambda-framework-dev` | development | + +## ローカルデプロイ + +### Bash版 +```bash +# 開発環境(デフォルトAWS Profile) +./deploy-env.sh development + +# 開発環境(指定AWS Profile) +./deploy-env.sh development dev-profile + +# 本番環境(指定AWS Profile) +./deploy-env.sh production prod-profile +``` + +### PowerShell版 +```powershell +# 開発環境(デフォルトAWS Profile) +.\deploy-env.ps1 development + +# 開発環境(指定AWS Profile) +.\deploy-env.ps1 development dev-profile + +# 本番環境(指定AWS Profile) +.\deploy-env.ps1 production prod-profile +``` \ No newline at end of file diff --git a/create_role.ps1 b/create_role.ps1 new file mode 100644 index 0000000..4c1df05 --- /dev/null +++ b/create_role.ps1 @@ -0,0 +1,1279 @@ +# PowerShellスクリプト: AWS CLIとSAM CLIのアクセス確認、GitHubユーザー情報取得、OIDC用IAMロール作成、GitHub Secrets自動登録 + +# 色付き出力用の関数 +function Write-Info { + param([string]$Message) + Write-Host "[INFO] $Message" -ForegroundColor Blue +} + +function Write-Success { + param([string]$Message) + Write-Host "[SUCCESS] $Message" -ForegroundColor Green +} + +function Write-Error { + param([string]$Message) + Write-Host "[ERROR] $Message" -ForegroundColor Red +} + +function Write-Warning { + param([string]$Message) + Write-Host "[WARNING] $Message" -ForegroundColor Yellow +} + +# 1. AWS CLIの確認 +Write-Info "AWS CLIの確認中..." +try { + $awsVersion = aws --version 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Success "AWS CLIが見つかりました: $awsVersion" + } else { + throw "AWS CLIが見つかりません" + } +} catch { + Write-Error "AWS CLIがインストールされていません" + exit 1 +} + +# 2. SAM CLIの確認 +Write-Info "SAM CLIの確認中..." +$SAM_CMD = $null + +# Windows環境でのSAM CLI確認 +Write-Info "Windows環境を検出しました" +try { + # sam.cmdを優先して確認 + Write-Info "sam.cmdの確認中..." + if (Get-Command sam.cmd -ErrorAction SilentlyContinue) { + try { + $samVersion = sam.cmd --version 2>$null + if ($LASTEXITCODE -eq 0) { + $SAM_CMD = "sam.cmd" + Write-Success "SAM CLIが見つかりました: sam.cmd ($samVersion)" + } else { + Write-Info "sam.cmdは存在しますが実行できません" + } + } catch { + Write-Info "sam.cmdの実行中にエラーが発生しました: $_" + } + } else { + Write-Info "sam.cmdが見つかりません" + } + + # sam.exeを確認 + if (-not $SAM_CMD) { + Write-Info "sam.exeの確認中..." + if (Get-Command sam.exe -ErrorAction SilentlyContinue) { + try { + $samVersion = sam.exe --version 2>$null + if ($LASTEXITCODE -eq 0) { + $SAM_CMD = "sam.exe" + Write-Success "SAM CLIが見つかりました: sam.exe ($samVersion)" + } else { + Write-Info "sam.exeは存在しますが実行できません" + } + } catch { + Write-Info "sam.exeの実行中にエラーが発生しました: $_" + } + } else { + Write-Info "sam.exeが見つかりません" + } + } + + # 通常のsamコマンドを確認 + if (-not $SAM_CMD) { + Write-Info "samの確認中..." + if (Get-Command sam -ErrorAction SilentlyContinue) { + try { + $samVersion = sam --version 2>$null + if ($LASTEXITCODE -eq 0) { + $SAM_CMD = "sam" + Write-Success "SAM CLIが見つかりました: sam ($samVersion)" + } else { + Write-Info "samは存在しますが実行できません" + } + } catch { + Write-Info "samの実行中にエラーが発生しました: $_" + } + } else { + Write-Info "samが見つかりません" + } + } + + if (-not $SAM_CMD) { + throw "SAM CLIが見つかりません" + + } +} catch { + Write-Warning "SAM CLIがインストールされていません" + $response = Read-Host "SAM CLIをインストールしますか? (y/N)" + if ($response -eq "y" -or $response -eq "Y") { + Write-Info "SAM CLIのインストール中..." + + # Windows用のインストール方法 + Write-Info "Windows環境でSAM CLIをインストール中..." + + $INSTALL_SUCCESS = $false + + # 方法1: wingetを使用 + if (Get-Command winget -ErrorAction SilentlyContinue) { + Write-Info "wingetを使用してインストールを試行中..." + try { + $result = winget install Amazon.AWSSAMCLI --accept-source-agreements --accept-package-agreements 2>&1 + if ($LASTEXITCODE -eq 0) { + $INSTALL_SUCCESS = $true + Write-Success "wingetでSAM CLIのインストールに成功しました" + } else { + Write-Warning "wingetでのインストールに失敗しました: $result" + } + } catch { + Write-Warning "wingetでのインストール中にエラーが発生しました: $_" + } + } else { + Write-Info "wingetが見つかりません" + } + + + + # 方法3: Scoopを使用 + if (-not $INSTALL_SUCCESS -and (Get-Command scoop -ErrorAction SilentlyContinue)) { + Write-Info "Scoopを使用してインストールを試行中..." + try { + $result = scoop install aws-sam-cli 2>&1 + if ($LASTEXITCODE -eq 0) { + $INSTALL_SUCCESS = $true + Write-Success "ScoopでSAM CLIのインストールに成功しました" + } else { + Write-Warning "Scoopでのインストールに失敗しました: $result" + } + } catch { + Write-Warning "Scoopでのインストール中にエラーが発生しました: $_" + } + } else { + Write-Info "Scoopが見つかりません" + } + + # 方法4: 直接ダウンロード + if (-not $INSTALL_SUCCESS) { + Write-Info "直接ダウンロードでインストールを試行中..." + try { + # 最新バージョンを取得 + $latestVersion = Invoke-RestMethod -Uri "https://api.github.com/repos/aws/aws-sam-cli/releases/latest" | Select-Object -ExpandProperty tag_name + $version = $latestVersion.TrimStart('v') + + # ダウンロードURL + $downloadUrl = "https://github.com/aws/aws-sam-cli/releases/download/$latestVersion/AWS_SAM_CLI_64_PY3.msi" + $installerPath = "$env:TEMP\AWS_SAM_CLI_64_PY3.msi" + + Write-Info "SAM CLI v$version をダウンロード中..." + Invoke-WebRequest -Uri $downloadUrl -OutFile $installerPath + + Write-Info "インストーラーを実行中..." + Start-Process -FilePath "msiexec.exe" -ArgumentList "/i `"$installerPath`" /quiet" -Wait + + # インストール確認 + Start-Sleep -Seconds 3 + if (Get-Command sam -ErrorAction SilentlyContinue) { + $INSTALL_SUCCESS = $true + Write-Success "直接ダウンロードでSAM CLIのインストールに成功しました" + } else { + Write-Warning "直接ダウンロードでのインストールに失敗しました" + } + + # 一時ファイルを削除 + if (Test-Path $installerPath) { + Remove-Item $installerPath -Force -ErrorAction SilentlyContinue + } + } catch { + Write-Warning "直接ダウンロードでのインストール中にエラーが発生しました: $_" + } + } + + if (-not $INSTALL_SUCCESS) { + Write-Error "すべてのインストール方法が失敗しました" + Write-Info "手動でSAM CLIをインストールしてください: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html" + exit 1 + } + + # インストール確認 + Write-Info "インストール確認中..." + Start-Sleep -Seconds 3 + + # PATHを再読み込み + $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH","User") + + # Windows環境でのSAM CLI確認 + Write-Info "インストール後のSAM CLI確認中..." + $samFound = $false + + # sam.exeを確認 + Write-Info "sam.exeの確認中..." + if (Get-Command sam.exe -ErrorAction SilentlyContinue) { + try { + $version = sam.exe --version 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "SAM CLIがインストールされました: sam.exe ($version)" + $samFound = $true + } else { + Write-Info "sam.exeは存在しますが実行できません" + } + } catch { + Write-Info "sam.exeの実行中にエラーが発生しました: $_" + } + } else { + Write-Info "sam.exeが見つかりません" + } + + # sam.cmdを確認 + if (-not $samFound) { + Write-Info "sam.cmdの確認中..." + if (Get-Command sam.cmd -ErrorAction SilentlyContinue) { + try { + $version = sam.cmd --version 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "SAM CLIがインストールされました: sam.cmd ($version)" + $samFound = $true + } else { + Write-Info "sam.cmdは存在しますが実行できません" + } + } catch { + Write-Info "sam.cmdの実行中にエラーが発生しました: $_" + } + } else { + Write-Info "sam.cmdが見つかりません" + } + } + + # 通常のsamコマンドを確認 + if (-not $samFound) { + Write-Info "samの確認中..." + if (Get-Command sam -ErrorAction SilentlyContinue) { + try { + $version = sam --version 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "SAM CLIがインストールされました: sam ($version)" + $samFound = $true + } else { + Write-Info "samは存在しますが実行できません" + } + } catch { + Write-Info "samの実行中にエラーが発生しました: $_" + } + } else { + Write-Info "samが見つかりません" + } + } + + if (-not $samFound) { + Write-Error "SAM CLIのインストール確認に失敗しました" + Write-Info "手動でインストールしてください: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html" + exit 1 + } + } else { + Write-Error "SAM CLIのインストールをスキップしました。手動でインストールしてください" + exit 1 + } +} + +# 3. GitHub CLIの確認 +Write-Info "GitHub CLIの確認中..." +$GITHUB_CLI_FOUND = $false + +# 複数の方法でGitHub CLIを検索 +try { + $ghVersion = gh --version 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Success "GitHub CLIがインストールされています: $ghVersion" + $GITHUB_CLI_FOUND = $true + } +} catch { + # エラーが発生した場合は無視して続行 +} + +# Windows環境での追加検索 +if (-not $GITHUB_CLI_FOUND) { + # Windows Git Bashでの検索 + $ghPaths = @( + "C:\Program Files\GitHub CLI\gh.exe", + "$env:USERPROFILE\AppData\Local\Microsoft\WinGet\Packages\GitHub.cli_Microsoft.Winget.Source_8wekyb3d8bbwe\LocalState\links\gh.exe", + "$env:USERPROFILE\AppData\Local\GitHubCLI\gh.exe", + "$env:USERPROFILE\scoop\apps\gh\current\gh.exe" + ) + + foreach ($path in $ghPaths) { + if (Test-Path $path) { + try { + $ghVersion = & $path --version 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Success "GitHub CLIがインストールされています: $ghVersion" + Write-Info "パス: $path" + $GITHUB_CLI_FOUND = $true + # PATHに追加 + $env:PATH = "$(Split-Path $path);$env:PATH" + break + } + } catch { + # エラーが発生した場合は無視して続行 + } + } + } + + # wingetでインストールされた場合の確認 + if (-not $GITHUB_CLI_FOUND -and (Get-Command winget -ErrorAction SilentlyContinue)) { + try { + $wingetGh = winget list GitHub.cli 2>$null | Select-String -Pattern "GitHub.cli" + if ($wingetGh) { + Write-Info "wingetでGitHub CLIがインストールされていることを確認しました" + # パスを再検索 + foreach ($path in $ghPaths) { + if (Test-Path $path) { + try { + $ghVersion = & $path --version 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Success "GitHub CLIがインストールされています: $ghVersion" + Write-Info "パス: $path" + $GITHUB_CLI_FOUND = $true + $env:PATH = "$(Split-Path $path);$env:PATH" + break + } + } catch { + # エラーが発生した場合は無視して続行 + } + } + } + } + } catch { + # エラーが発生した場合は無視して続行 + } + } + + # Scoopでインストールされた場合の確認 + if (-not $GITHUB_CLI_FOUND -and (Get-Command scoop -ErrorAction SilentlyContinue)) { + try { + $scoopGh = scoop list 2>$null | Select-String -Pattern "gh" + if ($scoopGh) { + Write-Info "scoopでGitHub CLIがインストールされていることを確認しました" + $scoopPath = "$env:USERPROFILE\scoop\apps\gh\current\gh.exe" + if (Test-Path $scoopPath) { + try { + $ghVersion = & $scoopPath --version 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Success "GitHub CLIがインストールされています: $ghVersion" + Write-Info "パス: $scoopPath" + $GITHUB_CLI_FOUND = $true + $env:PATH = "$(Split-Path $scoopPath);$env:PATH" + } + } catch { + # エラーが発生した場合は無視して続行 + } + } + } + } catch { + # エラーが発生した場合は無視して続行 + } + } +} + +if (-not $GITHUB_CLI_FOUND) { + Write-Warning "GitHub CLIがインストールされていません" + $response = Read-Host "GitHub CLIをインストールしますか? (y/N)" + if ($response -eq "y" -or $response -eq "Y") { + $GITHUB_CLI_AVAILABLE = $false + Write-Info "GitHub CLIのインストール中..." + + # Windows用のインストール方法 + Write-Info "Windows環境でGitHub CLIをインストール中..." + + $INSTALL_SUCCESS = $false + + # 方法1: wingetを使用 + if (Get-Command winget -ErrorAction SilentlyContinue) { + Write-Info "wingetを使用してインストールを試行中..." + try { + $result = winget install GitHub.cli --accept-source-agreements --accept-package-agreements 2>&1 + if ($LASTEXITCODE -eq 0) { + $INSTALL_SUCCESS = $true + Write-Success "wingetでGitHub CLIのインストールに成功しました" + } else { + Write-Warning "wingetでのインストールに失敗しました: $result" + } + } catch { + Write-Warning "wingetでのインストール中にエラーが発生しました: $_" + } + } else { + Write-Info "wingetが見つかりません" + } + + + + # 方法3: Scoopを使用 + if (-not $INSTALL_SUCCESS -and (Get-Command scoop -ErrorAction SilentlyContinue)) { + Write-Info "Scoopを使用してインストールを試行中..." + try { + $result = scoop install gh 2>&1 + if ($LASTEXITCODE -eq 0) { + $INSTALL_SUCCESS = $true + Write-Success "ScoopでGitHub CLIのインストールに成功しました" + } else { + Write-Warning "Scoopでのインストールに失敗しました: $result" + } + } catch { + Write-Warning "Scoopでのインストール中にエラーが発生しました: $_" + } + } else { + Write-Info "Scoopが見つからないか、既にインストール済みです" + } + + # 方法4: 直接ダウンロード + if (-not $INSTALL_SUCCESS) { + Write-Info "直接ダウンロードでインストールを試行中..." + try { + # アーキテクチャ判定 + $ARCH = if ([Environment]::Is64BitOperatingSystem) { "amd64" } else { "386" } + Write-Info "アーキテクチャ: $ARCH" + + # 最新バージョンの取得 + $LATEST_VERSION = (Invoke-RestMethod -Uri "https://api.github.com/repos/cli/cli/releases/latest" -UseBasicParsing).tag_name + $LATEST_VERSION = $LATEST_VERSION.TrimStart('v') + Write-Info "最新バージョン: $LATEST_VERSION" + + $DOWNLOAD_URL = "https://github.com/cli/cli/releases/download/v${LATEST_VERSION}/gh_${LATEST_VERSION}_windows_${ARCH}.zip" + $TEMP_DIR = "$env:TEMP\gh-install" + $ZIP_FILE = "$TEMP_DIR\gh.zip" + $INSTALL_DIR = "$env:ProgramFiles\GitHub CLI" + + Write-Info "ダウンロードURL: $DOWNLOAD_URL" + + # 一時ディレクトリを作成 + if (Test-Path $TEMP_DIR) { + Remove-Item $TEMP_DIR -Recurse -Force -ErrorAction SilentlyContinue + } + New-Item -ItemType Directory -Path $TEMP_DIR -Force | Out-Null + + # インストールディレクトリを作成 + if (-not (Test-Path $INSTALL_DIR)) { + New-Item -ItemType Directory -Path $INSTALL_DIR -Force | Out-Null + } + + # ダウンロード + Write-Info "ファイルをダウンロード中..." + Invoke-WebRequest -Uri $DOWNLOAD_URL -OutFile $ZIP_FILE -UseBasicParsing + + # 解凍 + Write-Info "ファイルを解凍中..." + Expand-Archive -Path $ZIP_FILE -DestinationPath $TEMP_DIR -Force + + # インストール + Write-Info "ファイルをインストール中..." + $GH_BIN = Get-ChildItem -Path $TEMP_DIR -Recurse -Name "gh.exe" | Select-Object -First 1 + if ($GH_BIN) { + $GH_PATH = Join-Path $TEMP_DIR $GH_BIN + $TARGET_PATH = Join-Path $INSTALL_DIR "gh.exe" + + Copy-Item -Path $GH_PATH -Destination $TARGET_PATH -Force + Write-Info "GitHub CLIを $TARGET_PATH にコピーしました" + + # PATHに追加 + $CURRENT_PATH = [Environment]::GetEnvironmentVariable("PATH", "Machine") + if ($CURRENT_PATH -notlike "*$INSTALL_DIR*") { + $NEW_PATH = "$CURRENT_PATH;$INSTALL_DIR" + [Environment]::SetEnvironmentVariable("PATH", $NEW_PATH, "Machine") + $env:PATH = "$env:PATH;$INSTALL_DIR" + Write-Info "PATH環境変数を更新しました" + } + + $INSTALL_SUCCESS = $true + Write-Success "直接ダウンロードでGitHub CLIのインストールに成功しました" + } else { + Write-Error "gh.exeが見つかりませんでした" + } + + # クリーンアップ + if (Test-Path $TEMP_DIR) { + Remove-Item $TEMP_DIR -Recurse -Force -ErrorAction SilentlyContinue + } + + } catch { + Write-Warning "直接ダウンロードでのインストールに失敗しました: $_" + } + } + + # インストール確認 + if ($INSTALL_SUCCESS) { + Write-Info "インストール確認中..." + Start-Sleep -Seconds 3 + + # PATHを再読み込み + $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH","User") + + if (Get-Command gh -ErrorAction SilentlyContinue) { + $version = gh --version 2>&1 + Write-Success "GitHub CLIがインストールされました: $version" + $GITHUB_CLI_AVAILABLE = $true + } else { + Write-Error "GitHub CLIのインストール確認に失敗しました" + Write-Info "手動でインストールしてください: https://cli.github.com/" + $GITHUB_CLI_AVAILABLE = $false + } + } else { + Write-Error "すべてのインストール方法が失敗しました" + Write-Info "手動でGitHub CLIをインストールしてください: https://cli.github.com/" + $GITHUB_CLI_AVAILABLE = $false + } + } else { + Write-Warning "GitHub CLIのインストールをスキップしました。手動でGitHub Secretsを設定してください" + $GITHUB_CLI_AVAILABLE = $false + } +} + +# GitHub CLIの利用可能性を最終確認 +if ($GITHUB_CLI_FOUND) { + $GITHUB_CLI_AVAILABLE = $true + Write-Info "GitHub CLIが利用可能です" +} + +# 4. 現在のGitブランチの確認 +Write-Info "現在のGitブランチの確認中..." +$CURRENT_BRANCH = git branch --show-current 2>$null +if (-not $CURRENT_BRANCH) { + $CURRENT_BRANCH = git rev-parse --abbrev-ref HEAD 2>$null +} + +if (-not $CURRENT_BRANCH) { + Write-Warning "Gitブランチを取得できませんでした。手動でブランチを選択してください" + Write-Host "" + Write-Host "=== ブランチの選択 ===" -ForegroundColor Cyan + Write-Host "1. main (本番環境用)" + Write-Host "2. deploy (開発環境用)" + Write-Host "3. その他" + Write-Host "" + + do { + $branchChoice = Read-Host "ブランチを選択してください (1-3)" + } while ($branchChoice -notmatch '^[1-3]$') + + switch ($branchChoice) { + "1" { + $CURRENT_BRANCH = "main" + Write-Info "本番環境用の設定を行います" + } + "2" { + $CURRENT_BRANCH = "deploy" + Write-Info "開発環境用の設定を行います" + } + "3" { + $CURRENT_BRANCH = Read-Host "ブランチ名を入力してください" + Write-Info "カスタムブランチ '$CURRENT_BRANCH' の設定を行います" + } + } +} else { + Write-Success "現在のブランチ: $CURRENT_BRANCH" + + if ($CURRENT_BRANCH -eq "main") { + Write-Info "本番環境用の設定を行います" + } elseif ($CURRENT_BRANCH -eq "deploy") { + Write-Info "開発環境用の設定を行います" + } else { + Write-Info "カスタムブランチ '$CURRENT_BRANCH' の設定を行います" + } +} + +# 環境設定の決定 +Write-Info "ブランチ '$CURRENT_BRANCH' に基づいて環境を設定中..." + +if ($CURRENT_BRANCH -eq "main") { + $ENVIRONMENT = "production" + $STACK_NAME = "lambda-framework-prod" + $SECRET_NAME = "AWS_ROLE_ARN_PROD" + Write-Info "mainブランチ → production環境 (本番環境)" +} elseif ($CURRENT_BRANCH -eq "deploy") { + $ENVIRONMENT = "development" + $STACK_NAME = "lambda-framework-dev" + $SECRET_NAME = "AWS_ROLE_ARN_DEV" + Write-Info "deployブランチ → development環境 (開発環境)" +} else { + $ENVIRONMENT = "development" + $STACK_NAME = "lambda-framework-dev" + $SECRET_NAME = "AWS_ROLE_ARN_DEV" + Write-Info "カスタムブランチ '$CURRENT_BRANCH' → development環境 (開発環境)" +} + +Write-Info "環境: $ENVIRONMENT" +Write-Info "スタック名: $STACK_NAME" +Write-Info "GitHub Secret名: $SECRET_NAME" + +# 5. AWS認証情報の確認 +Write-Info "AWS認証情報の確認中..." +try { + $callerIdentity = aws sts get-caller-identity 2>$null | ConvertFrom-Json + if ($LASTEXITCODE -eq 0) { + Write-Success "AWS認証情報が設定されています" + $CURRENT_ACCOUNT = $callerIdentity.Account + Write-Host "Account: $CURRENT_ACCOUNT" + Write-Host "User ID: $($callerIdentity.UserId)" + Write-Host "ARN: $($callerIdentity.Arn)" + + # AWSアカウントの選択 + Write-Host "" + Write-Host "=== AWSアカウントの選択 ===" -ForegroundColor Cyan + Write-Host "1. 現在のアカウントを使用 ($CURRENT_ACCOUNT)" + Write-Host "2. 別のAWSアカウントを設定" + Write-Host "" + + do { + $accountChoice = Read-Host "AWSアカウントを選択してください (1-2)" + } while ($accountChoice -notmatch '^[1-2]$') + + if ($accountChoice -eq "2") { + Write-Info "別のAWSアカウントを設定します" + Write-Host "" + Write-Host "=== AWS認証方法の選択 ===" -ForegroundColor Cyan + Write-Host "1. AWS CLI configure (アクセスキー/シークレットキー)" + Write-Host "2. AWS SSO (Single Sign-On)" + Write-Host "3. AWS IAM Identity Center (旧AWS SSO)" + Write-Host "4. AWS Profile (既存のプロファイル)" + Write-Host "" + + do { + $authChoice = Read-Host "認証方法を選択してください (1-4)" + } while ($authChoice -notmatch '^[1-4]$') + + switch ($authChoice) { + "1" { + Write-Info "AWS CLI configureを実行します" + Write-Host "アクセスキーID、シークレットアクセスキー、リージョンを入力してください" + aws configure + } + "2" { + Write-Info "AWS SSOを設定します" + $ssoStartUrl = Read-Host "SSO Start URLを入力してください (例: https://your-sso-portal.awsapps.com/start)" + $ssoRegion = Read-Host "SSO Regionを入力してください (例: us-east-1)" + $accountId = Read-Host "AWS Account IDを入力してください" + $roleName = Read-Host "SSO Role Nameを入力してください" + + aws configure sso-session --profile default + aws configure sso --profile default --sso-start-url $ssoStartUrl --sso-region $ssoRegion --account-id $accountId --role-name $roleName + } + "3" { + Write-Info "AWS IAM Identity Centerを設定します" + $ssoStartUrl = Read-Host "Identity Center Start URLを入力してください (例: https://your-portal.awsapps.com/start)" + $ssoRegion = Read-Host "Identity Center Regionを入力してください (例: us-east-1)" + $accountId = Read-Host "AWS Account IDを入力してください" + $roleName = Read-Host "Role Nameを入力してください" + + aws configure sso-session --profile default + aws configure sso --profile default --sso-start-url $ssoStartUrl --sso-region $ssoRegion --account-id $accountId --role-name $roleName + } + "4" { + Write-Info "既存のAWS Profileを選択します" + $profiles = aws configure list-profiles 2>$null + if ($profiles) { + Write-Host "利用可能なプロファイル:" + $profileArray = $profiles -split "`n" + for ($i = 0; $i -lt $profileArray.Count; $i++) { + Write-Host "$($i+1). $($profileArray[$i])" + } + Write-Host "" + $profileChoice = Read-Host "プロファイル番号を選択してください (1-$($profileArray.Count))" + if ($profileChoice -match '^\d+$' -and [int]$profileChoice -ge 1 -and [int]$profileChoice -le $profileArray.Count) { + $selectedProfile = $profileArray[[int]$profileChoice - 1] + $env:AWS_PROFILE = $selectedProfile + Write-Success "プロファイル '$selectedProfile' が選択されました" + } else { + Write-Error "無効な選択です。デフォルトプロファイルを使用します" + } + } else { + Write-Warning "利用可能なプロファイルが見つかりません。AWS CLI configureを実行します" + aws configure + } + } + } + + # 認証情報の再確認 + Write-Info "認証情報の確認中..." + try { + $newCallerIdentity = aws sts get-caller-identity 2>$null | ConvertFrom-Json + if ($LASTEXITCODE -eq 0) { + Write-Success "AWS認証情報が正常に設定されました" + Write-Host "Account: $($newCallerIdentity.Account)" + Write-Host "User ID: $($newCallerIdentity.UserId)" + Write-Host "ARN: $($newCallerIdentity.Arn)" + $callerIdentity = $newCallerIdentity + } else { + throw "AWS認証情報の設定に失敗しました" + } + } catch { + Write-Error "AWS認証情報の設定に失敗しました" + exit 1 + } + } else { + Write-Info "現在のAWSアカウントを使用します" + } + } else { + throw "AWS認証情報が設定されていません" + } +} catch { + Write-Warning "AWS認証情報が設定されていません。AWS認証方法を選択してください" + Write-Host "" + Write-Host "=== AWS認証方法の選択 ===" -ForegroundColor Cyan + Write-Host "1. AWS CLI configure (アクセスキー/シークレットキー)" + Write-Host "2. AWS SSO (Single Sign-On)" + Write-Host "3. AWS IAM Identity Center (旧AWS SSO)" + Write-Host "4. AWS Profile (既存のプロファイル)" + Write-Host "" + + do { + $authChoice = Read-Host "認証方法を選択してください (1-4)" + } while ($authChoice -notmatch '^[1-4]$') + + switch ($authChoice) { + "1" { + Write-Info "AWS CLI configureを実行します" + Write-Host "アクセスキーID、シークレットアクセスキー、リージョンを入力してください" + aws configure + } + "2" { + Write-Info "AWS SSOを設定します" + $ssoStartUrl = Read-Host "SSO Start URLを入力してください (例: https://your-sso-portal.awsapps.com/start)" + $ssoRegion = Read-Host "SSO Regionを入力してください (例: us-east-1)" + $accountId = Read-Host "AWS Account IDを入力してください" + $roleName = Read-Host "SSO Role Nameを入力してください" + + aws configure sso-session --profile default + aws configure sso --profile default --sso-start-url $ssoStartUrl --sso-region $ssoRegion --account-id $accountId --role-name $roleName + } + "3" { + Write-Info "AWS IAM Identity Centerを設定します" + $ssoStartUrl = Read-Host "Identity Center Start URLを入力してください (例: https://your-portal.awsapps.com/start)" + $ssoRegion = Read-Host "Identity Center Regionを入力してください (例: us-east-1)" + $accountId = Read-Host "AWS Account IDを入力してください" + $roleName = Read-Host "Role Nameを入力してください" + + aws configure sso-session --profile default + aws configure sso --profile default --sso-start-url $ssoStartUrl --sso-region $ssoRegion --account-id $accountId --role-name $roleName + } + "4" { + Write-Info "既存のAWS Profileを選択します" + $profiles = aws configure list-profiles 2>$null + if ($profiles) { + Write-Host "利用可能なプロファイル:" + $profileArray = $profiles -split "`n" + for ($i = 0; $i -lt $profileArray.Count; $i++) { + Write-Host "$($i+1). $($profileArray[$i])" + } + Write-Host "" + $profileChoice = Read-Host "プロファイル番号を選択してください (1-$($profileArray.Count))" + if ($profileChoice -match '^\d+$' -and [int]$profileChoice -ge 1 -and [int]$profileChoice -le $profileArray.Count) { + $selectedProfile = $profileArray[[int]$profileChoice - 1] + $env:AWS_PROFILE = $selectedProfile + Write-Success "プロファイル '$selectedProfile' が選択されました" + } else { + Write-Error "無効な選択です。デフォルトプロファイルを使用します" + } + } else { + Write-Warning "利用可能なプロファイルが見つかりません。AWS CLI configureを実行します" + aws configure + } + } + } + + # 認証情報の再確認 + Write-Info "認証情報の確認中..." + $callerIdentity = aws sts get-caller-identity 2>$null | ConvertFrom-Json + if ($LASTEXITCODE -eq 0) { + Write-Success "AWS認証情報が正常に設定されました" + Write-Host "Account: $($callerIdentity.Account)" + Write-Host "User ID: $($callerIdentity.UserId)" + Write-Host "ARN: $($callerIdentity.Arn)" + } else { + Write-Error "AWS認証情報の設定に失敗しました" + exit 1 + } +} + +# 5. GitHubユーザー情報の取得 +Write-Info "GitHubユーザー情報の取得中..." + +# GitHub CLIの利用可能性を再確認 +$GITHUB_CLI_WORKING = $false +$GITHUB_USERNAME = $null +$GITHUB_REPO_NAME = $null + +if ($GITHUB_CLI_AVAILABLE) { + Write-Info "GitHub CLIの認証状態を確認中..." + + # GitHub CLIの認証状態を確認 + try { + $ghStatus = gh auth status 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Success "GitHub CLIにログイン済みです" + $GITHUB_CLI_WORKING = $true + } else { + Write-Warning "GitHub CLIにログインしていません" + Write-Host "" + Write-Host "=== GitHub CLIログイン ===" -ForegroundColor Cyan + Write-Host "GitHub CLIにログインする必要があります" + Write-Host "1. ブラウザでログイン" + Write-Host "2. トークンでログイン" + Write-Host "3. 手動でユーザー情報を入力" + Write-Host "" + + do { + $loginChoice = Read-Host "ログイン方法を選択してください (1-3)" + } while ($loginChoice -notmatch '^[1-3]$') + + switch ($loginChoice) { + "1" { + Write-Info "ブラウザでログインを開始します..." + try { + gh auth login --web + if ($LASTEXITCODE -eq 0) { + Write-Success "GitHub CLIログインに成功しました" + $GITHUB_CLI_WORKING = $true + } else { + Write-Error "GitHub CLIログインに失敗しました" + } + } catch { + Write-Error "GitHub CLIログインに失敗しました: $_" + } + } + "2" { + Write-Info "トークンでログインします..." + $githubToken = Read-Host "GitHub Personal Access Tokenを入力してください" + try { + $githubToken | gh auth login --with-token + if ($LASTEXITCODE -eq 0) { + Write-Success "GitHub CLIログインに成功しました" + $GITHUB_CLI_WORKING = $true + } else { + Write-Error "GitHub CLIログインに失敗しました" + } + } catch { + Write-Error "GitHub CLIログインに失敗しました: $_" + } + } + "3" { + Write-Info "手動でユーザー情報を入力します" + $GITHUB_CLI_WORKING = $false + } + } + } + } catch { + Write-Error "GitHub CLIの認証状態確認に失敗しました: $_" + $GITHUB_CLI_WORKING = $false + } + + # GitHub CLIが動作する場合、ユーザー情報を取得 + if ($GITHUB_CLI_WORKING) { + Write-Info "GitHubユーザー情報を取得中..." + + # ユーザー情報の取得 + try { + $userResponse = gh api user 2>$null + if ($LASTEXITCODE -eq 0 -and $userResponse) { + $userData = $userResponse | ConvertFrom-Json + if ($userData.login) { + $GITHUB_USERNAME = $userData.login + Write-Success "GitHubユーザー名: $GITHUB_USERNAME" + } else { + Write-Error "GitHubユーザー名の取得に失敗しました" + $GITHUB_CLI_WORKING = $false + } + } else { + Write-Error "GitHub APIからのユーザー情報取得に失敗しました" + $GITHUB_CLI_WORKING = $false + } + } catch { + Write-Error "GitHubユーザー情報の取得に失敗しました: $_" + $GITHUB_CLI_WORKING = $false + } + + # リポジトリ情報の取得 + if ($GITHUB_CLI_WORKING) { + try { + $repoUrl = git remote get-url origin 2>$null + if ($LASTEXITCODE -eq 0 -and $repoUrl) { + $GITHUB_REPO_NAME = $repoUrl -replace '.*[:/]([^/]+/[^/]+)\.git$', '$1' -replace '.*/', '' + Write-Success "GitHubリポジトリ名: $GITHUB_REPO_NAME" + } else { + Write-Warning "リポジトリ情報の取得に失敗しました。手動で入力してください" + $GITHUB_CLI_WORKING = $false + } + } catch { + Write-Warning "リポジトリ情報の取得に失敗しました: $_" + $GITHUB_CLI_WORKING = $false + } + } + } +} + +# GitHub CLIが利用できない場合、手動で入力 +if (-not $GITHUB_CLI_WORKING) { + Write-Warning "GitHub CLIが利用できません。手動でGitHubユーザー名とリポジトリ名を入力してください" + $GITHUB_USERNAME = Read-Host "GitHubユーザー名を入力してください" + $GITHUB_REPO_NAME = Read-Host "GitHubリポジトリ名を入力してください" +} + +# 6. AWSアカウントIDの取得 +Write-Info "AWSアカウントIDの取得中..." +$AWS_ACCOUNT_ID = aws sts get-caller-identity --query Account --output text 2>$null +Write-Success "AWSアカウントID: $AWS_ACCOUNT_ID" + +# AWSリージョンの確認 +Write-Info "AWSリージョンの確認" +$AWS_REGION_INPUT = Read-Host "AWSリージョンを入力してください (デフォルト: ap-northeast-1)" +$AWS_REGION = if ($AWS_REGION_INPUT) { $AWS_REGION_INPUT } else { "ap-northeast-1" } +Write-Success "AWSリージョン: $AWS_REGION" + +# プロジェクト名の確認 +Write-Info "プロジェクト名の確認" +$PROJECT_NAME_INPUT = Read-Host "プロジェクト名を入力してください (デフォルト: LambdaFramework)" +$PROJECT_NAME = if ($PROJECT_NAME_INPUT) { $PROJECT_NAME_INPUT } else { "LambdaFramework" } +Write-Success "プロジェクト名: $PROJECT_NAME" + +# S3バケット名の確認 +Write-Info "S3バケット名の確認" +$S3_BUCKET_INPUT = Read-Host "S3バケット名を入力してください (デフォルト: cn-seba-aws-sam-cli-managed-default-samclisourcebucket)" +$S3_BUCKET = if ($S3_BUCKET_INPUT) { $S3_BUCKET_INPUT } else { "cn-seba-aws-sam-cli-managed-default-samclisourcebucket" } +Write-Success "S3バケット名: $S3_BUCKET" + +# 7. OIDCプロバイダーの選択 +Write-Info "OIDCプロバイダーの選択中..." + +# 既存のOIDCプロバイダー一覧を取得 +Write-Info "既存のOIDCプロバイダーを取得中..." +$OIDC_PROVIDERS = aws iam list-open-id-connect-providers --query 'OpenIDConnectProviderList[].Arn' --output text 2>$null + +# GitHub Actions用のOIDCプロバイダーARN +$GITHUB_OIDC_ARN = "arn:aws:iam:$AWS_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com" + +# 選択肢を準備 +Write-Host "" +Write-Host "=== 利用可能なOIDCプロバイダー ===" -ForegroundColor Cyan +Write-Host "0. 新規作成: GitHub Actions用OIDCプロバイダー" +Write-Host " ($GITHUB_OIDC_ARN)" + +# 既存のプロバイダーを表示 +if ($OIDC_PROVIDERS) { + $PROVIDER_ARRAY = $OIDC_PROVIDERS -split "`t" + for ($i = 0; $i -lt $PROVIDER_ARRAY.Count; $i++) { + $PROVIDER_ARN = $PROVIDER_ARRAY[$i] + $PROVIDER_URL = aws iam get-open-id-connect-provider --open-id-connect-provider-arn $PROVIDER_ARN --query 'Url' --output text 2>$null + Write-Host "$($i+1). $PROVIDER_ARN" + Write-Host " URL: $PROVIDER_URL" + } +} else { + Write-Host "既存のOIDCプロバイダーが見つかりません" +} + +Write-Host "" +$OIDC_CHOICE = Read-Host "OIDCプロバイダーを選択してください (0-$($PROVIDER_ARRAY.Count))" + +# 選択に基づいてOIDCプロバイダーARNを設定 +if ($OIDC_CHOICE -eq "0") { + Write-Info "新規OIDCプロバイダーを作成中..." + $OIDC_PROVIDER_ARN = $GITHUB_OIDC_ARN + + # OIDCプロバイダーが既に存在するかチェック + try { + aws iam get-open-id-connect-provider --open-id-connect-provider-arn $OIDC_PROVIDER_ARN 2>$null | Out-Null + if ($LASTEXITCODE -eq 0) { + Write-Success "OIDCプロバイダーは既に存在します" + } else { + throw "OIDCプロバイダーが存在しません" + } + } catch { + aws iam create-open-id-connect-provider ` + --url https://token.actions.githubusercontent.com ` + --client-id-list sts.amazonaws.com ` + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Success "OIDCプロバイダーが作成されました" + } else { + Write-Error "OIDCプロバイダーの作成に失敗しました" + exit 1 + } + } +} else { + # 既存のプロバイダーを選択 + if ($OIDC_PROVIDERS -and [int]$OIDC_CHOICE -ge 1 -and [int]$OIDC_CHOICE -le $PROVIDER_ARRAY.Count) { + $SELECTED_INDEX = [int]$OIDC_CHOICE - 1 + $OIDC_PROVIDER_ARN = $PROVIDER_ARRAY[$SELECTED_INDEX] + Write-Success "選択されたOIDCプロバイダー: $OIDC_PROVIDER_ARN" + } else { + Write-Error "無効な選択です。デフォルトで新規作成します" + $OIDC_PROVIDER_ARN = $GITHUB_OIDC_ARN + + try { + aws iam get-open-id-connect-provider --open-id-connect-provider-arn $OIDC_PROVIDER_ARN 2>$null | Out-Null + if ($LASTEXITCODE -eq 0) { + Write-Success "OIDCプロバイダーは既に存在します" + } else { + throw "OIDCプロバイダーが存在しません" + } + } catch { + aws iam create-open-id-connect-provider ` + --url https://token.actions.githubusercontent.com ` + --client-id-list sts.amazonaws.com ` + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Success "OIDCプロバイダーが作成されました" + } else { + Write-Error "OIDCプロバイダーの作成に失敗しました" + exit 1 + } + } + } +} + +# 8. IAMロールの作成 +Write-Info "IAMロールの作成について確認します" +$DEFAULT_ROLE_NAME = "$PROJECT_NAME-github-actions-role" +$ROLE_NAME_INPUT = Read-Host "IAMロール名を入力してください (デフォルト: $DEFAULT_ROLE_NAME)" +$ROLE_NAME = if ($ROLE_NAME_INPUT) { $ROLE_NAME_INPUT } else { $DEFAULT_ROLE_NAME } +Write-Info "IAMロールの作成中... ($ROLE_NAME)" + +$TRUST_POLICY = @" +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": "$OIDC_PROVIDER_ARN" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", + "token.actions.githubusercontent.com:sub": "repo:$GITHUB_USERNAME/$GITHUB_REPO_NAME:ref:refs/heads/deploy" + } + } + } + ] +} +"@ + +# ロールが存在するかチェック +try { + $result = aws iam get-role --role-name $ROLE_NAME 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "IAMロールは既に存在します: $ROLE_NAME" + } else { + throw "IAMロールが存在しません" + } +} catch { + Write-Info "IAMロールを作成中..." + + # 一時ファイルを作成してポリシードキュメントを保存 + $TEMP_POLICY_FILE = "$env:TEMP\trust-policy.json" + $TRUST_POLICY | Out-File -FilePath $TEMP_POLICY_FILE -Encoding UTF8 + + try { + $result = aws iam create-role --role-name $ROLE_NAME --assume-role-policy-document file://$TEMP_POLICY_FILE 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "IAMロールが作成されました: $ROLE_NAME" + } else { + Write-Error "IAMロールの作成に失敗しました: $result" + exit 1 + } + } finally { + # 一時ファイルを削除 + if (Test-Path $TEMP_POLICY_FILE) { + Remove-Item $TEMP_POLICY_FILE -Force -ErrorAction SilentlyContinue + } + } +} + +# 9. ポリシーの作成とアタッチ +Write-Info "IAMポリシーの作成について確認します" +$DEFAULT_POLICY_NAME = "$PROJECT_NAME-github-actions-policy" +$POLICY_NAME_INPUT = Read-Host "IAMポリシー名を入力してください (デフォルト: $DEFAULT_POLICY_NAME)" +$POLICY_NAME = if ($POLICY_NAME_INPUT) { $POLICY_NAME_INPUT } else { $DEFAULT_POLICY_NAME } +Write-Info "IAMポリシーの作成中... ($POLICY_NAME)" + +$POLICY_DOCUMENT = @" +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "cloudformation:*", + "s3:*", + "lambda:*", + "iam:*", + "logs:*" + ], + "Resource": "*" + } + ] +} +"@ + +# ポリシーが存在するかチェック +Write-Info "IAMポリシーの存在を確認中: $POLICY_NAME" +$policyExists = $false + +# より確実な存在確認方法 +$checkResult = aws iam list-policies --scope Local --query "Policies[?PolicyName=='$POLICY_NAME'].Arn" --output text 2>&1 +if ($LASTEXITCODE -eq 0 -and $checkResult -and $checkResult -ne "None") { + Write-Success "IAMポリシーは既に存在します: $POLICY_NAME" + $policyExists = $true +} else { + Write-Info "IAMポリシーが見つかりません。作成を試行します..." +} + +if (-not $policyExists) { + Write-Info "IAMポリシーを作成中..." + + # 一時ファイルを作成してポリシードキュメントを保存 + $TEMP_POLICY_FILE = "$env:TEMP\policy-document.json" + $POLICY_DOCUMENT | Out-File -FilePath $TEMP_POLICY_FILE -Encoding UTF8 + + try { + $result = aws iam create-policy --policy-name $POLICY_NAME --policy-document file://$TEMP_POLICY_FILE 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "IAMポリシーが作成されました: $POLICY_NAME" + } else { + # 作成に失敗した場合、既に存在する可能性があるので再確認 + $recheckResult = aws iam list-policies --scope Local --query "Policies[?PolicyName=='$POLICY_NAME'].Arn" --output text 2>&1 + if ($LASTEXITCODE -eq 0 -and $recheckResult -and $recheckResult -ne "None") { + Write-Success "IAMポリシーは既に存在します: $POLICY_NAME" + } else { + Write-Error "IAMポリシーの作成に失敗しました: $result" + exit 1 + } + } + } finally { + # 一時ファイルを削除 + if (Test-Path $TEMP_POLICY_FILE) { + Remove-Item $TEMP_POLICY_FILE -Force -ErrorAction SilentlyContinue + } + } +} + +# ポリシーをロールにアタッチ +Write-Info "ポリシーをロールにアタッチ中..." +aws iam attach-role-policy --role-name $ROLE_NAME --policy-arn "arn:aws:iam:$AWS_ACCOUNT_ID:policy/$POLICY_NAME" 2>$null +if ($LASTEXITCODE -eq 0) { + Write-Success "ポリシーがロールにアタッチされました" +} else { + Write-Warning "ポリシーのアタッチに失敗しました(既にアタッチされている可能性があります)" +} + +# 10. GitHub Secretsの自動登録 +if ($GITHUB_CLI_AVAILABLE) { + Write-Info "GitHub Secretsの自動登録について確認します" + + # GitHub CLIの認証状況を確認 + Write-Info "GitHub CLIの認証状況を確認中..." + $authStatus = gh auth status 2>&1 + if ($LASTEXITCODE -ne 0) { + Write-Warning "GitHub CLIにログインしていません。ログインしてください" + gh auth login + $authStatus = gh auth status 2>&1 + if ($LASTEXITCODE -ne 0) { + Write-Error "GitHub CLIの認証に失敗しました" + $GITHUB_CLI_AVAILABLE = $false + } + } + + if ($GITHUB_CLI_AVAILABLE) { + $response = Read-Host "GitHub Secretsを自動登録しますか? (y/N)" + if ($response -eq "y" -or $response -eq "Y") { + Write-Info "GitHub Secretsの自動登録中..." + + # 現在のリポジトリを確認 + Write-Info "現在のリポジトリを確認中..." + $currentRepo = (gh repo view --json nameWithOwner 2>&1 | ConvertFrom-Json).nameWithOwner + if ($LASTEXITCODE -eq 0) { + Write-Success "リポジトリ: $currentRepo" + } else { + Write-Warning "リポジトリの確認に失敗しました: $currentRepo" + } + + # Repository Secretsの登録(機密情報) + Write-Info "=== Repository Secretsの登録 ===" + + # 環境別AWS_ROLE_ARNの登録 + $AWS_ROLE_ARN = "arn:aws:iam:$AWS_ACCOUNT_ID:role/$ROLE_NAME" + Write-Info "$SECRET_NAMEをRepository Secretsに登録中: $AWS_ROLE_ARN" + $result = gh secret set $SECRET_NAME --body $AWS_ROLE_ARN 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "$SECRET_NAME がRepository Secretsに登録されました" + } else { + Write-Warning "$SECRET_NAME の登録に失敗しました: $result" + } + + # S3_BUCKETの登録 + Write-Info "S3_BUCKETをRepository Secretsに登録中: $S3_BUCKET" + $result = gh secret set S3_BUCKET --body $S3_BUCKET 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "S3_BUCKET がRepository Secretsに登録されました" + } else { + Write-Warning "S3_BUCKET の登録に失敗しました: $result" + } + + # Repository Variablesの登録(非機密情報) + Write-Info "=== Repository Variablesの登録 ===" + + # AWS_REGIONの登録 + Write-Info "AWS_REGIONをRepository Variablesに登録中: $AWS_REGION" + $result = gh variable set AWS_REGION --body $AWS_REGION 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "AWS_REGION がRepository Variablesに登録されました" + } else { + Write-Warning "AWS_REGION の登録に失敗しました: $result" + } + + # PROJECT_NAMEの登録 + Write-Info "PROJECT_NAMEをRepository Variablesに登録中: $PROJECT_NAME" + $result = gh variable set PROJECT_NAME --body $PROJECT_NAME 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "PROJECT_NAME がRepository Variablesに登録されました" + } else { + Write-Warning "PROJECT_NAME の登録に失敗しました: $result" + } + } else { + Write-Info "GitHub Secretsの自動登録をスキップしました" + } + } +} else { + Write-Warning "GitHub CLIが利用できないため、手動でGitHub Secretsを設定してください" +} + +# 11. 結果の表示 +Write-Success "設定が完了しました!" +Write-Host "" +Write-Host "=== 設定情報 ===" -ForegroundColor Cyan +Write-Host "AWSアカウントID: $AWS_ACCOUNT_ID" +Write-Host "GitHubユーザー名: $GITHUB_USERNAME" +Write-Host "GitHubリポジトリ名: $GITHUB_REPO_NAME" +Write-Host "IAMロール名: $ROLE_NAME" +Write-Host "IAMロールARN: arn:aws:iam:$AWS_ACCOUNT_ID:role/$ROLE_NAME" +Write-Host "" + +if ($GITHUB_CLI_AVAILABLE) { + Write-Success "GitHub SecretsとVariablesが自動登録されました" + Write-Host "登録されたRepository Secrets:" -ForegroundColor Yellow + Write-Host "- $SECRET_NAME" + Write-Host "- S3_BUCKET" + Write-Host "登録されたRepository Variables:" -ForegroundColor Yellow + Write-Host "- AWS_REGION" + Write-Host "- PROJECT_NAME" +} else { + Write-Host "手動でGitHubに以下を設定してください:" -ForegroundColor Yellow + Write-Host "" + Write-Host "Repository Secrets:" -ForegroundColor Cyan + Write-Host "Name: $SECRET_NAME" + Write-Host "Value: arn:aws:iam:$AWS_ACCOUNT_ID:role/$ROLE_NAME" + Write-Host "Name: S3_BUCKET" + Write-Host "Value: $S3_BUCKET" + Write-Host "" + Write-Host "Repository Variables:" -ForegroundColor Cyan + Write-Host "Name: AWS_REGION" + Write-Host "Value: $AWS_REGION" + Write-Host "Name: PROJECT_NAME" + Write-Host "Value: $PROJECT_NAME" +} \ No newline at end of file diff --git a/create_role.sh b/create_role.sh new file mode 100644 index 0000000..1a90bf2 --- /dev/null +++ b/create_role.sh @@ -0,0 +1,1220 @@ +#!/bin/bash + +# 色付き出力用の関数 +print_info() { + echo -e "\033[34m[INFO]\033[0m $1" +} + +print_success() { + echo -e "\033[32m[SUCCESS]\033[0m $1" +} + +print_error() { + echo -e "\033[31m[ERROR]\033[0m $1" +} + +print_warning() { + echo -e "\033[33m[WARNING]\033[0m $1" +} + +# 1. AWS CLIの確認 +print_info "AWS CLIの確認中..." +if ! command -v aws &> /dev/null; then + print_error "AWS CLIがインストールされていません" + exit 1 +fi + +print_success "AWS CLIが見つかりました: $(aws --version)" + +# 2. SAM CLIの確認 +print_info "SAM CLIの確認中..." +SAM_CMD="sam" + +# Windows環境でのSAM CLI確認 +if [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "cygwin"* ]] || [[ "$(uname)" == "MINGW"* ]] || [[ "$(uname)" == "MSYS"* ]]; then + print_info "Windows環境を検出しました: $OSTYPE ($(uname))" + # Windows環境ではsam.cmdを優先して確認 + print_info "sam.cmdの確認中..." + if command -v sam.cmd &> /dev/null; then + # 実際にバージョン確認を試行 + if sam.cmd --version &> /dev/null; then + SAM_CMD="sam.cmd" + print_success "SAM CLIが見つかりました: sam.cmd ($(sam.cmd --version 2>/dev/null | head -n1))" + else + print_info "sam.cmdは存在しますが実行できません" + fi + else + print_info "sam.cmdが見つかりません" + fi + + if [[ -z "$SAM_CMD" ]]; then + print_info "sam.exeの確認中..." + if command -v sam.exe &> /dev/null; then + # 実際にバージョン確認を試行 + if sam.exe --version &> /dev/null; then + SAM_CMD="sam.exe" + print_success "SAM CLIが見つかりました: sam.exe ($(sam.exe --version 2>/dev/null | head -n1))" + else + print_info "sam.exeは存在しますが実行できません" + fi + else + print_info "sam.exeが見つかりません" + fi + fi + + if [[ -z "$SAM_CMD" ]]; then + print_info "samの確認中..." + if command -v sam &> /dev/null; then + # 実際にバージョン確認を試行 + if sam --version &> /dev/null; then + SAM_CMD="sam" + print_success "SAM CLIが見つかりました: sam ($(sam --version 2>/dev/null | head -n1))" + else + print_info "samは存在しますが実行できません" + fi + else + print_info "samが見つかりません" + fi + fi +else + print_info "非Windows環境を検出しました: $OSTYPE" + # 非Windows環境では通常のsamコマンドを確認 + if command -v sam &> /dev/null; then + SAM_CMD="sam" + else + SAM_CMD="" + fi +fi + +if [[ -z "$SAM_CMD" ]]; then + print_warning "SAM CLIがインストールされていません" + read -p "SAM CLIをインストールしますか? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + print_info "SAM CLIのインストール中..." + + # OS判定とインストール + if [[ "$OSTYPE" == "linux-gnu"* ]] || [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "cygwin"* ]]; then + # Linux または Windows Git Bash + if [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "cygwin"* ]]; then + print_info "Windows Git Bash環境でSAM CLIをインストール中..." + else + print_info "Linux環境でSAM CLIをインストール中..." + fi + + INSTALL_SUCCESS=false + + # 方法1: pipを使用 + if command -v pip3 &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "pip3を使用してインストールを試行中..." + if pip3 install aws-sam-cli >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "pip3でSAM CLIのインストールに成功しました" + fi + fi + + # 方法2: apt-get (Debian/Ubuntu) + if command -v apt-get &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "apt-getを使用してインストールを試行中..." + if wget https://github.com/aws/aws-sam-cli/releases/latest/download/install-sam-cli.sh -O /tmp/install-sam-cli.sh 2>/dev/null; then + if chmod +x /tmp/install-sam-cli.sh 2>/dev/null; then + if sudo /tmp/install-sam-cli.sh >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "apt-getでSAM CLIのインストールに成功しました" + fi + fi + rm -f /tmp/install-sam-cli.sh + fi + fi + + # 方法3: yum (RHEL/CentOS) + if command -v yum &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "yumを使用してインストールを試行中..." + if wget https://github.com/aws/aws-sam-cli/releases/latest/download/install-sam-cli.sh -O /tmp/install-sam-cli.sh 2>/dev/null; then + if chmod +x /tmp/install-sam-cli.sh 2>/dev/null; then + if sudo /tmp/install-sam-cli.sh >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "yumでSAM CLIのインストールに成功しました" + fi + fi + rm -f /tmp/install-sam-cli.sh + fi + fi + + # 方法4: pip (Windows Git Bash用) + if command -v pip3 &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "pip3を使用してインストールを試行中..." + if pip3 install aws-sam-cli >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "pip3でSAM CLIのインストールに成功しました" + fi + fi + + # 方法5: 直接ダウンロード + if ! $INSTALL_SUCCESS; then + print_info "直接ダウンロードでインストールを試行中..." + ARCH=$(uname -m) + if [[ "$ARCH" == "x86_64" ]]; then + ARCH="x86_64" + elif [[ "$ARCH" == "aarch64" ]]; then + ARCH="arm64" + fi + + # 最新バージョンを取得 + LATEST_VERSION=$(curl -s https://api.github.com/repos/aws/aws-sam-cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + VERSION=${LATEST_VERSION#v} + + if curl -L "https://github.com/aws/aws-sam-cli/releases/download/$LATEST_VERSION/aws-sam-cli-linux-$ARCH.zip" -o /tmp/sam-cli.zip 2>/dev/null; then + if unzip -q /tmp/sam-cli.zip -d /tmp 2>/dev/null; then + # Windows Git Bashの場合はsudoを使わずにコピー + if [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "cygwin"* ]]; then + if cp /tmp/sam-installation/sam /usr/local/bin/ 2>/dev/null || cp /tmp/sam-installation/sam ~/.local/bin/ 2>/dev/null; then + INSTALL_SUCCESS=true + print_success "直接ダウンロードでSAM CLIのインストールに成功しました" + fi + else + if sudo cp /tmp/sam-installation/sam /usr/local/bin/ 2>/dev/null; then + INSTALL_SUCCESS=true + print_success "直接ダウンロードでSAM CLIのインストールに成功しました" + fi + fi + fi + rm -f /tmp/sam-cli.zip + rm -rf /tmp/sam-installation + fi + fi + + elif [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + print_info "macOS環境でSAM CLIをインストール中..." + + INSTALL_SUCCESS=false + + # 方法1: Homebrew + if command -v brew &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "Homebrewを使用してインストールを試行中..." + if brew install aws-sam-cli >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "HomebrewでSAM CLIのインストールに成功しました" + fi + fi + + # 方法2: pip + if command -v pip3 &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "pip3を使用してインストールを試行中..." + if pip3 install aws-sam-cli >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "pip3でSAM CLIのインストールに成功しました" + fi + fi + + # 方法3: 直接ダウンロード + if ! $INSTALL_SUCCESS; then + print_info "直接ダウンロードでインストールを試行中..." + ARCH=$(uname -m) + if [[ "$ARCH" == "x86_64" ]]; then + ARCH="x86_64" + elif [[ "$ARCH" == "arm64" ]]; then + ARCH="arm64" + fi + + # 最新バージョンを取得 + LATEST_VERSION=$(curl -s https://api.github.com/repos/aws/aws-sam-cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + VERSION=${LATEST_VERSION#v} + + if curl -L "https://github.com/aws/aws-sam-cli/releases/download/$LATEST_VERSION/aws-sam-cli-mac-$ARCH.zip" -o /tmp/sam-cli.zip 2>/dev/null; then + if unzip -q /tmp/sam-cli.zip -d /tmp 2>/dev/null; then + if sudo cp /tmp/sam-installation/sam /usr/local/bin/ 2>/dev/null; then + INSTALL_SUCCESS=true + print_success "直接ダウンロードでSAM CLIのインストールに成功しました" + fi + fi + rm -f /tmp/sam-cli.zip + rm -rf /tmp/sam-installation + fi + fi + + else + print_error "サポートされていないOSです。手動でSAM CLIをインストールしてください" + print_info "インストール方法: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html" + exit 1 + fi + + if ! $INSTALL_SUCCESS; then + print_error "すべてのインストール方法が失敗しました" + print_info "手動でSAM CLIをインストールしてください: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html" + exit 1 + fi + + # インストール確認 + print_info "インストール確認中..." + sleep 3 + + # Windows環境でのSAM CLI確認 + if [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "cygwin"* ]] || [[ "$(uname)" == "MINGW"* ]] || [[ "$(uname)" == "MSYS"* ]]; then + if command -v sam.exe &> /dev/null; then + print_success "SAM CLIがインストールされました: $(sam.exe --version)" + elif command -v sam.cmd &> /dev/null; then + print_success "SAM CLIがインストールされました: $(sam.cmd --version)" + elif command -v sam &> /dev/null; then + print_success "SAM CLIがインストールされました: $(sam --version)" + else + print_error "SAM CLIのインストール確認に失敗しました" + print_info "手動でインストールしてください: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html" + exit 1 + fi + else + if command -v sam &> /dev/null; then + print_success "SAM CLIがインストールされました: $(sam --version)" + else + print_error "SAM CLIのインストール確認に失敗しました" + print_info "手動でインストールしてください: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html" + exit 1 + fi + fi + else + print_error "SAM CLIのインストールをスキップしました。手動でインストールしてください" + exit 1 + fi +else + # Windows環境でのSAM CLI確認 + if [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "cygwin"* ]] || [[ "$(uname)" == "MINGW"* ]] || [[ "$(uname)" == "MSYS"* ]]; then + if command -v sam.exe &> /dev/null; then + print_success "SAM CLIが見つかりました: $(sam.exe --version)" + elif command -v sam.cmd &> /dev/null; then + print_success "SAM CLIが見つかりました: $(sam.cmd --version)" + elif command -v sam &> /dev/null; then + print_success "SAM CLIが見つかりました: $(sam --version)" + fi + else + print_success "SAM CLIが見つかりました: $(sam --version)" + fi +fi + +# 3. GitHub CLIの確認 +print_info "GitHub CLIの確認中..." +GITHUB_CLI_FOUND=false + +# 複数の方法でGitHub CLIを検索 +if command -v gh &> /dev/null; then + GH_VERSION=$(gh --version 2>/dev/null | head -n1) + if [ $? -eq 0 ]; then + print_success "GitHub CLIがインストールされています: $GH_VERSION" + GITHUB_CLI_FOUND=true + fi +fi + +# Windows環境での追加検索 +if [ "$GITHUB_CLI_FOUND" = false ] && [[ "$OSTYPE" == "msys"* || "$OSTYPE" == "cygwin"* || "$OSTYPE" == "MINGW"* || "$OSTYPE" == "MSYS"* ]]; then + # Windows Git Bashでの検索 + if [ -f "/c/Program Files/GitHub CLI/gh.exe" ]; then + GH_VERSION=$("/c/Program Files/GitHub CLI/gh.exe" --version 2>/dev/null | head -n1) + if [ $? -eq 0 ]; then + print_success "GitHub CLIがインストールされています: $GH_VERSION" + GITHUB_CLI_FOUND=true + # PATHに追加 + export PATH="/c/Program Files/GitHub CLI:$PATH" + fi + fi + + # wingetでインストールされた場合 + if [ "$GITHUB_CLI_FOUND" = false ] && command -v winget &> /dev/null; then + WINGET_GH=$(winget list GitHub.cli 2>/dev/null | grep -i "github.cli") + if [ -n "$WINGET_GH" ]; then + print_info "wingetでGitHub CLIがインストールされていることを確認しました" + # パスを再検索 + for path in "/c/Users/$USER/AppData/Local/Microsoft/WinGet/Packages/GitHub.cli_Microsoft.Winget.Source_8wekyb3d8bbwe/LocalState/links" \ + "/c/Program Files/GitHub CLI" \ + "/c/Users/$USER/AppData/Local/GitHubCLI"; do + if [ -f "$path/gh.exe" ]; then + GH_VERSION=$("$path/gh.exe" --version 2>/dev/null | head -n1) + if [ $? -eq 0 ]; then + print_success "GitHub CLIがインストールされています: $GH_VERSION" + GITHUB_CLI_FOUND=true + export PATH="$path:$PATH" + break + fi + fi + done + fi + fi + + # Scoopでインストールされた場合 + if [ "$GITHUB_CLI_FOUND" = false ] && command -v scoop &> /dev/null; then + SCOOP_GH=$(scoop list 2>/dev/null | grep -i "gh") + if [ -n "$SCOOP_GH" ]; then + print_info "scoopでGitHub CLIがインストールされていることを確認しました" + if [ -f "/c/Users/$USER/scoop/apps/gh/current/gh.exe" ]; then + GH_VERSION=$("/c/Users/$USER/scoop/apps/gh/current/gh.exe" --version 2>/dev/null | head -n1) + if [ $? -eq 0 ]; then + print_success "GitHub CLIがインストールされています: $GH_VERSION" + GITHUB_CLI_FOUND=true + export PATH="/c/Users/$USER/scoop/apps/gh/current:$PATH" + fi + fi + fi + fi +fi + +if [ "$GITHUB_CLI_FOUND" = false ]; then + print_warning "GitHub CLIがインストールされていません" + read -p "GitHub CLIをインストールしますか? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + GITHUB_CLI_AVAILABLE=false + print_info "GitHub CLIのインストール中..." + + # OS判定とインストール + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + # Linux + print_info "Linux環境でGitHub CLIをインストール中..." + + # 複数のインストール方法を試行 + INSTALL_SUCCESS=false + + # 方法1: apt-get (Debian/Ubuntu) + if command -v apt-get &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "apt-getを使用してインストールを試行中..." + if curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg 2>/dev/null; then + if echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null; then + if sudo apt-get update >/dev/null 2>&1 && sudo apt-get install gh -y >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "apt-getでGitHub CLIのインストールに成功しました" + fi + fi + fi + fi + + # 方法2: yum (RHEL/CentOS) + if command -v yum &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "yumを使用してインストールを試行中..." + if sudo yum install gh -y >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "yumでGitHub CLIのインストールに成功しました" + fi + fi + + # 方法3: dnf (Fedora) + if command -v dnf &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "dnfを使用してインストールを試行中..." + if sudo dnf install gh -y >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "dnfでGitHub CLIのインストールに成功しました" + fi + fi + + # 方法4: 直接ダウンロード + if ! $INSTALL_SUCCESS; then + print_info "直接ダウンロードでインストールを試行中..." + ARCH=$(uname -m) + if [[ "$ARCH" == "x86_64" ]]; then + ARCH="amd64" + elif [[ "$ARCH" == "aarch64" ]]; then + ARCH="arm64" + fi + + if curl -L "https://github.com/cli/cli/releases/latest/download/gh_linux_${ARCH}.tar.gz" -o /tmp/gh.tar.gz 2>/dev/null; then + if tar -xzf /tmp/gh.tar.gz -C /tmp 2>/dev/null; then + if sudo cp /tmp/gh_*/bin/gh /usr/local/bin/ 2>/dev/null; then + INSTALL_SUCCESS=true + print_success "直接ダウンロードでGitHub CLIのインストールに成功しました" + fi + fi + rm -f /tmp/gh.tar.gz + rm -rf /tmp/gh_* + fi + fi + + if ! $INSTALL_SUCCESS; then + print_error "すべてのインストール方法が失敗しました" + print_info "手動でGitHub CLIをインストールしてください: https://cli.github.com/" + GITHUB_CLI_AVAILABLE=false + fi + + elif [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + print_info "macOS環境でGitHub CLIをインストール中..." + + INSTALL_SUCCESS=false + + # 方法1: Homebrew + if command -v brew &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "Homebrewを使用してインストールを試行中..." + if brew install gh >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "HomebrewでGitHub CLIのインストールに成功しました" + fi + fi + + # 方法2: 直接ダウンロード + if ! $INSTALL_SUCCESS; then + print_info "直接ダウンロードでインストールを試行中..." + ARCH=$(uname -m) + if [[ "$ARCH" == "x86_64" ]]; then + ARCH="amd64" + elif [[ "$ARCH" == "arm64" ]]; then + ARCH="arm64" + fi + + if curl -L "https://github.com/cli/cli/releases/latest/download/gh_macOS_${ARCH}.tar.gz" -o /tmp/gh.tar.gz 2>/dev/null; then + if tar -xzf /tmp/gh.tar.gz -C /tmp 2>/dev/null; then + if sudo cp /tmp/gh_*/bin/gh /usr/local/bin/ 2>/dev/null; then + INSTALL_SUCCESS=true + print_success "直接ダウンロードでGitHub CLIのインストールに成功しました" + fi + fi + rm -f /tmp/gh.tar.gz + rm -rf /tmp/gh_* + fi + fi + + if ! $INSTALL_SUCCESS; then + print_error "すべてのインストール方法が失敗しました" + print_info "手動でGitHub CLIをインストールしてください: https://cli.github.com/" + GITHUB_CLI_AVAILABLE=false + fi + + elif [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "cygwin"* ]] || [[ "$(uname)" == "MINGW"* ]] || [[ "$(uname)" == "MSYS"* ]]; then + # Windows Git Bash / MSYS2 / Cygwin + print_info "Windows環境でGitHub CLIをインストール中..." + + INSTALL_SUCCESS=false + + # 方法1: winget (Windows Package Manager) + if command -v winget &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "wingetを使用してインストールを試行中..." + if winget install GitHub.cli >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "wingetでGitHub CLIのインストールに成功しました" + fi + fi + + # 方法2: Scoop + if command -v scoop &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "Scoopを使用してインストールを試行中..." + if scoop install gh >/dev/null 2>&1; then + INSTALL_SUCCESS=true + print_success "ScoopでGitHub CLIのインストールに成功しました" + fi + fi + + # 方法3: pip3 (Python経由) + if command -v pip3 &> /dev/null && ! $INSTALL_SUCCESS; then + print_info "pip3を使用してインストールを試行中..." + if pip3 install gh 2>/dev/null; then + INSTALL_SUCCESS=true + print_success "pip3でGitHub CLIのインストールに成功しました" + fi + fi + + # 方法4: 直接ダウンロード + if ! $INSTALL_SUCCESS; then + print_info "直接ダウンロードでインストールを試行中..." + ARCH=$(uname -m) + if [[ "$ARCH" == "x86_64" ]]; then + ARCH="amd64" + elif [[ "$ARCH" == "aarch64" ]]; then + ARCH="arm64" + fi + + # Windows用のダウンロードURL + if curl -L "https://github.com/cli/cli/releases/latest/download/gh_windows_${ARCH}.zip" -o /tmp/gh.zip 2>/dev/null; then + if unzip -q /tmp/gh.zip -d /tmp 2>/dev/null; then + # 実行可能ファイルをPATHに追加 + if [[ -d "$HOME/bin" ]]; then + cp /tmp/gh_*/bin/gh.exe "$HOME/bin/" 2>/dev/null + export PATH="$HOME/bin:$PATH" + elif [[ -d "/usr/local/bin" ]]; then + cp /tmp/gh_*/bin/gh.exe /usr/local/bin/ 2>/dev/null + else + # カレントディレクトリにコピー + cp /tmp/gh_*/bin/gh.exe ./ 2>/dev/null + export PATH="$(pwd):$PATH" + fi + INSTALL_SUCCESS=true + print_success "直接ダウンロードでGitHub CLIのインストールに成功しました" + fi + rm -f /tmp/gh.zip + rm -rf /tmp/gh_* + fi + fi + + if ! $INSTALL_SUCCESS; then + print_error "すべてのインストール方法が失敗しました" + print_info "手動でGitHub CLIをインストールしてください: https://cli.github.com/" + print_info "Windows環境では以下を試してください:" + print_info "1. winget install GitHub.cli" + print_info "2. scoop install gh" + print_info "3. https://cli.github.com/ から直接ダウンロード" + GITHUB_CLI_AVAILABLE=false + fi + + else + print_error "サポートされていないOSです。手動でGitHub CLIをインストールしてください" + print_info "インストール方法: https://cli.github.com/" + GITHUB_CLI_AVAILABLE=false + fi + + # インストール確認 + if command -v gh &> /dev/null; then + print_success "GitHub CLIがインストールされました: $(gh --version)" + GITHUB_CLI_AVAILABLE=true + else + print_error "GitHub CLIのインストールに失敗しました" + GITHUB_CLI_AVAILABLE=false + fi + else + print_warning "GitHub CLIのインストールをスキップしました。手動でGitHub Secretsを設定してください" + GITHUB_CLI_AVAILABLE=false + fi +else + print_success "GitHub CLIが見つかりました: $(gh --version)" + GITHUB_CLI_AVAILABLE=true +fi + +# GitHub CLIの利用可能性を最終確認 +if [ "$GITHUB_CLI_FOUND" = true ]; then + GITHUB_CLI_AVAILABLE=true + print_info "GitHub CLIが利用可能です" +fi + +# 4. 現在のGitブランチの確認 +print_info "現在のGitブランチの確認中..." +CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || git rev-parse --abbrev-ref HEAD 2>/dev/null) + +if [[ -z "$CURRENT_BRANCH" ]]; then + print_warning "Gitブランチを取得できませんでした。手動でブランチを選択してください" + echo "" + echo "=== ブランチの選択 ===" + echo "1. main (本番環境用)" + echo "2. deploy (開発環境用)" + echo "3. その他" + echo "" + + while true; do + read -p "ブランチを選択してください (1-3): " branch_choice + if [[ "$branch_choice" =~ ^[1-3]$ ]]; then + break + fi + echo "無効な選択です。1-3の数字を入力してください。" + done + + case $branch_choice in + 1) + CURRENT_BRANCH="main" + print_info "本番環境用の設定を行います" + ;; + 2) + CURRENT_BRANCH="deploy" + print_info "開発環境用の設定を行います" + ;; + 3) + read -p "ブランチ名を入力してください: " CURRENT_BRANCH + print_info "カスタムブランチ '$CURRENT_BRANCH' の設定を行います" + ;; + esac +else + print_success "現在のブランチ: $CURRENT_BRANCH" + + if [[ "$CURRENT_BRANCH" == "main" ]]; then + print_info "本番環境用の設定を行います" + elif [[ "$CURRENT_BRANCH" == "deploy" ]]; then + print_info "開発環境用の設定を行います" + else + print_info "カスタムブランチ '$CURRENT_BRANCH' の設定を行います" + fi +fi + +# 環境設定の決定 +print_info "ブランチ '$CURRENT_BRANCH' に基づいて環境を設定中..." + +if [[ "$CURRENT_BRANCH" == "main" ]]; then + ENVIRONMENT="production" + STACK_NAME="lambda-framework-prod" + SECRET_NAME="AWS_ROLE_ARN_PROD" + print_info "mainブランチ → production環境 (本番環境)" +elif [[ "$CURRENT_BRANCH" == "deploy" ]]; then + ENVIRONMENT="development" + STACK_NAME="lambda-framework-dev" + SECRET_NAME="AWS_ROLE_ARN_DEV" + print_info "deployブランチ → development環境 (開発環境)" +else + ENVIRONMENT="development" + STACK_NAME="lambda-framework-dev" + SECRET_NAME="AWS_ROLE_ARN_DEV" + print_info "カスタムブランチ '$CURRENT_BRANCH' → development環境 (開発環境)" +fi + +print_info "環境: $ENVIRONMENT" +print_info "スタック名: $STACK_NAME" +print_info "GitHub Secret名: $SECRET_NAME" + +# 5. AWS認証情報の確認 +print_info "AWS認証情報の確認中..." +if aws sts get-caller-identity &> /dev/null; then + print_success "AWS認証情報が設定されています" + CALLER_IDENTITY=$(aws sts get-caller-identity) + CURRENT_ACCOUNT=$(echo "$CALLER_IDENTITY" | grep -o '"Account": "[^"]*"' | sed 's/"Account": "//;s/"//') + echo "Account: $CURRENT_ACCOUNT" + echo "User ID: $(echo "$CALLER_IDENTITY" | grep -o '"UserId": "[^"]*"' | sed 's/"UserId": "//;s/"//')" + echo "ARN: $(echo "$CALLER_IDENTITY" | grep -o '"Arn": "[^"]*"' | sed 's/"Arn": "//;s/"//')" + + # AWSアカウントの選択 + echo "" + echo "=== AWSアカウントの選択 ===" + echo "1. 現在のアカウントを使用 ($CURRENT_ACCOUNT)" + echo "2. 別のAWSアカウントを設定" + echo "" + + while true; do + read -p "AWSアカウントを選択してください (1-2): " account_choice + if [[ "$account_choice" =~ ^[1-2]$ ]]; then + break + fi + echo "無効な選択です。1-2の数字を入力してください。" + done + + if [[ "$account_choice" == "2" ]]; then + print_info "別のAWSアカウントを設定します" + echo "" + echo "=== AWS認証方法の選択 ===" + echo "1. AWS CLI configure (アクセスキー/シークレットキー)" + echo "2. AWS SSO (Single Sign-On)" + echo "3. AWS IAM Identity Center (旧AWS SSO)" + echo "4. AWS Profile (既存のプロファイル)" + echo "" + + while true; do + read -p "認証方法を選択してください (1-4): " auth_choice + if [[ "$auth_choice" =~ ^[1-4]$ ]]; then + break + fi + echo "無効な選択です。1-4の数字を入力してください。" + done + + case $auth_choice in + 1) + print_info "AWS CLI configureを実行します" + echo "アクセスキーID、シークレットアクセスキー、リージョンを入力してください" + aws configure + ;; + 2) + print_info "AWS SSOを設定します" + read -p "SSO Start URLを入力してください (例: https://your-sso-portal.awsapps.com/start): " sso_start_url + read -p "SSO Regionを入力してください (例: us-east-1): " sso_region + read -p "AWS Account IDを入力してください: " account_id + read -p "SSO Role Nameを入力してください: " role_name + + aws configure sso-session --profile default + aws configure sso --profile default --sso-start-url "$sso_start_url" --sso-region "$sso_region" --account-id "$account_id" --role-name "$role_name" + ;; + 3) + print_info "AWS IAM Identity Centerを設定します" + read -p "Identity Center Start URLを入力してください (例: https://your-portal.awsapps.com/start): " sso_start_url + read -p "Identity Center Regionを入力してください (例: us-east-1): " sso_region + read -p "AWS Account IDを入力してください: " account_id + read -p "Role Nameを入力してください: " role_name + + aws configure sso-session --profile default + aws configure sso --profile default --sso-start-url "$sso_start_url" --sso-region "$sso_region" --account-id "$account_id" --role-name "$role_name" + ;; + 4) + print_info "既存のAWS Profileを選択します" + profiles=$(aws configure list-profiles 2>/dev/null) + if [ -n "$profiles" ]; then + echo "利用可能なプロファイル:" + profile_array=($profiles) + for i in "${!profile_array[@]}"; do + echo "$((i+1)). ${profile_array[$i]}" + done + echo "" + read -p "プロファイル番号を選択してください (1-${#profile_array[@]}): " profile_choice + if [[ "$profile_choice" =~ ^[0-9]+$ ]] && [ "$profile_choice" -ge 1 ] && [ "$profile_choice" -le "${#profile_array[@]}" ]; then + selected_profile="${profile_array[$((profile_choice-1))]}" + export AWS_PROFILE="$selected_profile" + print_success "プロファイル '$selected_profile' が選択されました" + else + print_error "無効な選択です。デフォルトプロファイルを使用します" + fi + else + print_warning "利用可能なプロファイルが見つかりません。AWS CLI configureを実行します" + aws configure + fi + ;; + esac + + # 認証情報の再確認 + print_info "認証情報の確認中..." + if aws sts get-caller-identity &> /dev/null; then + print_success "AWS認証情報が正常に設定されました" + CALLER_IDENTITY=$(aws sts get-caller-identity) + echo "Account: $(echo "$CALLER_IDENTITY" | grep -o '"Account": "[^"]*"' | sed 's/"Account": "//;s/"//')" + echo "User ID: $(echo "$CALLER_IDENTITY" | grep -o '"UserId": "[^"]*"' | sed 's/"UserId": "//;s/"//')" + echo "ARN: $(echo "$CALLER_IDENTITY" | grep -o '"Arn": "[^"]*"' | sed 's/"Arn": "//;s/"//')" + else + print_error "AWS認証情報の設定に失敗しました" + exit 1 + fi + else + print_info "現在のAWSアカウントを使用します" + fi +else + print_warning "AWS認証情報が設定されていません。AWS認証方法を選択してください" + echo "" + echo "=== AWS認証方法の選択 ===" + echo "1. AWS CLI configure (アクセスキー/シークレットキー)" + echo "2. AWS SSO (Single Sign-On)" + echo "3. AWS IAM Identity Center (旧AWS SSO)" + echo "4. AWS Profile (既存のプロファイル)" + echo "" + + while true; do + read -p "認証方法を選択してください (1-4): " auth_choice + if [[ "$auth_choice" =~ ^[1-4]$ ]]; then + break + fi + echo "無効な選択です。1-4の数字を入力してください。" + done + + case $auth_choice in + 1) + print_info "AWS CLI configureを実行します" + echo "アクセスキーID、シークレットアクセスキー、リージョンを入力してください" + aws configure + ;; + 2) + print_info "AWS SSOを設定します" + read -p "SSO Start URLを入力してください (例: https://your-sso-portal.awsapps.com/start): " sso_start_url + read -p "SSO Regionを入力してください (例: us-east-1): " sso_region + read -p "AWS Account IDを入力してください: " account_id + read -p "SSO Role Nameを入力してください: " role_name + + aws configure sso-session --profile default + aws configure sso --profile default --sso-start-url "$sso_start_url" --sso-region "$sso_region" --account-id "$account_id" --role-name "$role_name" + ;; + 3) + print_info "AWS IAM Identity Centerを設定します" + read -p "Identity Center Start URLを入力してください (例: https://your-portal.awsapps.com/start): " sso_start_url + read -p "Identity Center Regionを入力してください (例: us-east-1): " sso_region + read -p "AWS Account IDを入力してください: " account_id + read -p "Role Nameを入力してください: " role_name + + aws configure sso-session --profile default + aws configure sso --profile default --sso-start-url "$sso_start_url" --sso-region "$sso_region" --account-id "$account_id" --role-name "$role_name" + ;; + 4) + print_info "既存のAWS Profileを選択します" + profiles=$(aws configure list-profiles 2>/dev/null) + if [ -n "$profiles" ]; then + echo "利用可能なプロファイル:" + profile_array=($profiles) + for i in "${!profile_array[@]}"; do + echo "$((i+1)). ${profile_array[$i]}" + done + echo "" + read -p "プロファイル番号を選択してください (1-${#profile_array[@]}): " profile_choice + if [[ "$profile_choice" =~ ^[0-9]+$ ]] && [ "$profile_choice" -ge 1 ] && [ "$profile_choice" -le "${#profile_array[@]}" ]; then + selected_profile="${profile_array[$((profile_choice-1))]}" + export AWS_PROFILE="$selected_profile" + print_success "プロファイル '$selected_profile' が選択されました" + else + print_error "無効な選択です。デフォルトプロファイルを使用します" + fi + else + print_warning "利用可能なプロファイルが見つかりません。AWS CLI configureを実行します" + aws configure + fi + ;; + esac + + # 認証情報の再確認 + print_info "認証情報の確認中..." + if aws sts get-caller-identity &> /dev/null; then + print_success "AWS認証情報が正常に設定されました" + CALLER_IDENTITY=$(aws sts get-caller-identity) + echo "Account: $(echo "$CALLER_IDENTITY" | grep -o '"Account": "[^"]*"' | sed 's/"Account": "//;s/"//')" + echo "User ID: $(echo "$CALLER_IDENTITY" | grep -o '"UserId": "[^"]*"' | sed 's/"UserId": "//;s/"//')" + echo "ARN: $(echo "$CALLER_IDENTITY" | grep -o '"Arn": "[^"]*"' | sed 's/"Arn": "//;s/"//')" + else + print_error "AWS認証情報の設定に失敗しました" + exit 1 + fi +fi + +# 5. GitHubユーザー情報の取得 +print_info "GitHubユーザー情報の取得中..." + +# GitHub CLIの利用可能性を再確認 +GITHUB_CLI_WORKING=false +if [ "$GITHUB_CLI_AVAILABLE" = true ]; then + print_info "GitHub CLIの認証状態を確認中..." + + # GitHub CLIの認証状態を確認 + if gh auth status &> /dev/null; then + print_success "GitHub CLIにログイン済みです" + GITHUB_CLI_WORKING=true + else + print_warning "GitHub CLIにログインしていません" + echo "" + echo "=== GitHub CLIログイン ===" + echo "GitHub CLIにログインする必要があります" + echo "1. ブラウザでログイン" + echo "2. トークンでログイン" + echo "3. 手動でユーザー情報を入力" + echo "" + + while true; do + read -p "ログイン方法を選択してください (1-3): " login_choice + if [[ "$login_choice" =~ ^[1-3]$ ]]; then + break + fi + echo "無効な選択です。1-3の数字を入力してください。" + done + + case $login_choice in + 1) + print_info "ブラウザでログインを開始します..." + if gh auth login --web; then + print_success "GitHub CLIログインに成功しました" + GITHUB_CLI_WORKING=true + else + print_error "GitHub CLIログインに失敗しました" + fi + ;; + 2) + print_info "トークンでログインします..." + read -p "GitHub Personal Access Tokenを入力してください: " github_token + if gh auth login --with-token <<< "$github_token"; then + print_success "GitHub CLIログインに成功しました" + GITHUB_CLI_WORKING=true + else + print_error "GitHub CLIログインに失敗しました" + fi + ;; + 3) + print_info "手動でユーザー情報を入力します" + GITHUB_CLI_WORKING=false + ;; + esac + fi + + # GitHub CLIが動作する場合、ユーザー情報を取得 + if [ "$GITHUB_CLI_WORKING" = true ]; then + print_info "GitHubユーザー情報を取得中..." + + # ユーザー情報の取得 + USER_RESPONSE=$(gh api user 2>/dev/null) + if [ $? -eq 0 ] && [ -n "$USER_RESPONSE" ]; then + GITHUB_USERNAME=$(echo "$USER_RESPONSE" | grep -o '"login": "[^"]*"' | sed 's/"login": "//;s/"//') + if [ -n "$GITHUB_USERNAME" ]; then + print_success "GitHubユーザー名: $GITHUB_USERNAME" + else + print_error "GitHubユーザー名の取得に失敗しました" + GITHUB_CLI_WORKING=false + fi + else + print_error "GitHub APIからのユーザー情報取得に失敗しました" + GITHUB_CLI_WORKING=false + fi + + # リポジトリ情報の取得 + if [ "$GITHUB_CLI_WORKING" = true ]; then + REPO_RESPONSE=$(gh api repos/$GITHUB_USERNAME/$(basename $(git remote get-url origin 2>/dev/null) .git) 2>/dev/null) + if [ $? -eq 0 ] && [ -n "$REPO_RESPONSE" ]; then + GITHUB_REPO_NAME=$(basename $(git remote get-url origin 2>/dev/null) .git) + print_success "GitHubリポジトリ名: $GITHUB_REPO_NAME" + else + print_warning "リポジトリ情報の取得に失敗しました。手動で入力してください" + GITHUB_CLI_WORKING=false + fi + fi + fi +fi + +# GitHub CLIが利用できない場合、手動で入力 +if [ "$GITHUB_CLI_WORKING" = false ]; then + print_warning "GitHub CLIが利用できません。手動でGitHubユーザー名とリポジトリ名を入力してください" + read -p "GitHubユーザー名を入力してください: " GITHUB_USERNAME + read -p "GitHubリポジトリ名を入力してください: " GITHUB_REPO_NAME +fi + +# 6. AWSアカウントIDの取得 +print_info "AWSアカウントIDの取得中..." +AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +print_success "AWSアカウントID: $AWS_ACCOUNT_ID" + +# AWSリージョンの確認 +print_info "AWSリージョンの確認" +read -p "AWSリージョンを入力してください (デフォルト: ap-northeast-1): " AWS_REGION_INPUT +AWS_REGION=${AWS_REGION_INPUT:-"ap-northeast-1"} +print_success "AWSリージョン: $AWS_REGION" + +# プロジェクト名の確認 +print_info "プロジェクト名の確認" +read -p "プロジェクト名を入力してください (デフォルト: LambdaFramework): " PROJECT_NAME_INPUT +PROJECT_NAME=${PROJECT_NAME_INPUT:-"LambdaFramework"} +print_success "プロジェクト名: $PROJECT_NAME" + +# S3バケット名の確認 +print_info "S3バケット名の確認" +read -p "S3バケット名を入力してください (デフォルト: cn-seba-aws-sam-cli-managed-default-samclisourcebucket): " S3_BUCKET_INPUT +S3_BUCKET=${S3_BUCKET_INPUT:-"cn-seba-aws-sam-cli-managed-default-samclisourcebucket"} +print_success "S3バケット名: $S3_BUCKET" + +# 7. OIDCプロバイダーの選択 +print_info "OIDCプロバイダーの選択中..." + +# 既存のOIDCプロバイダー一覧を取得 +print_info "既存のOIDCプロバイダーを取得中..." +OIDC_PROVIDERS=$(aws iam list-open-id-connect-providers --query 'OpenIDConnectProviderList[].Arn' --output text 2>/dev/null) + +# GitHub Actions用のOIDCプロバイダーARN +GITHUB_OIDC_ARN="arn:aws:iam::$AWS_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com" + +# 選択肢を準備 +echo "" +echo "=== 利用可能なOIDCプロバイダー ===" +echo "0. 新規作成: GitHub Actions用OIDCプロバイダー" +echo " ($GITHUB_OIDC_ARN)" + +# 既存のプロバイダーを表示 +if [ -n "$OIDC_PROVIDERS" ]; then + IFS=$'\t' read -ra PROVIDER_ARRAY <<< "$OIDC_PROVIDERS" + for i in "${!PROVIDER_ARRAY[@]}"; do + PROVIDER_ARN="${PROVIDER_ARRAY[$i]}" + PROVIDER_URL=$(aws iam get-open-id-connect-provider --open-id-connect-provider-arn "$PROVIDER_ARN" --query 'Url' --output text 2>/dev/null) + echo "$((i+1)). $PROVIDER_ARN" + echo " URL: $PROVIDER_URL" + done +else + echo "既存のOIDCプロバイダーが見つかりません" +fi + +echo "" +read -p "OIDCプロバイダーを選択してください (0-${#PROVIDER_ARRAY[@]}): " OIDC_CHOICE + +# 選択に基づいてOIDCプロバイダーARNを設定 +if [ "$OIDC_CHOICE" = "0" ]; then + print_info "新規OIDCプロバイダーを作成中..." + OIDC_PROVIDER_ARN="$GITHUB_OIDC_ARN" + + # OIDCプロバイダーが既に存在するかチェック + if ! aws iam get-open-id-connect-provider --open-id-connect-provider-arn "$OIDC_PROVIDER_ARN" &> /dev/null; then + aws iam create-open-id-connect-provider \ + --url https://token.actions.githubusercontent.com \ + --client-id-list sts.amazonaws.com \ + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 + print_success "OIDCプロバイダーが作成されました" + else + print_success "OIDCプロバイダーは既に存在します" + fi +else + # 既存のプロバイダーを選択 + if [ -n "$OIDC_PROVIDERS" ] && [ "$OIDC_CHOICE" -ge 1 ] && [ "$OIDC_CHOICE" -le "${#PROVIDER_ARRAY[@]}" ]; then + SELECTED_INDEX=$((OIDC_CHOICE-1)) + OIDC_PROVIDER_ARN="${PROVIDER_ARRAY[$SELECTED_INDEX]}" + print_success "選択されたOIDCプロバイダー: $OIDC_PROVIDER_ARN" + else + print_error "無効な選択です。デフォルトで新規作成します" + OIDC_PROVIDER_ARN="$GITHUB_OIDC_ARN" + + if ! aws iam get-open-id-connect-provider --open-id-connect-provider-arn "$OIDC_PROVIDER_ARN" &> /dev/null; then + aws iam create-open-id-connect-provider \ + --url https://token.actions.githubusercontent.com \ + --client-id-list sts.amazonaws.com \ + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 + print_success "OIDCプロバイダーが作成されました" + else + print_success "OIDCプロバイダーは既に存在します" + fi + fi +fi + +# 8. IAMロールの作成 +print_info "IAMロールの作成について確認します" +DEFAULT_ROLE_NAME="${PROJECT_NAME}-github-actions-role" +read -p "IAMロール名を入力してください (デフォルト: $DEFAULT_ROLE_NAME): " ROLE_NAME_INPUT +ROLE_NAME=${ROLE_NAME_INPUT:-$DEFAULT_ROLE_NAME} +print_info "IAMロールの作成中... ($ROLE_NAME)" +TRUST_POLICY=$(cat < /dev/null; then + print_info "IAMロールを作成中..." + aws iam create-role \ + --role-name "$ROLE_NAME" \ + --assume-role-policy-document "$TRUST_POLICY" + print_success "IAMロールが作成されました: $ROLE_NAME" +else + print_success "IAMロールは既に存在します: $ROLE_NAME" +fi + +# 9. ポリシーの作成とアタッチ +print_info "IAMポリシーの作成について確認します" +DEFAULT_POLICY_NAME="${PROJECT_NAME}-github-actions-policy" +read -p "IAMポリシー名を入力してください (デフォルト: $DEFAULT_POLICY_NAME): " POLICY_NAME_INPUT +POLICY_NAME=${POLICY_NAME_INPUT:-$DEFAULT_POLICY_NAME} +print_info "IAMポリシーの作成中... ($POLICY_NAME)" +POLICY_DOCUMENT=$(cat </dev/null) +if [ $? -eq 0 ] && [ -n "$CHECK_RESULT" ] && [ "$CHECK_RESULT" != "None" ]; then + print_success "IAMポリシーは既に存在します: $POLICY_NAME" + POLICY_EXISTS=true +else + print_info "IAMポリシーが見つかりません。作成を試行します..." +fi + +if [ "$POLICY_EXISTS" = false ]; then + print_info "IAMポリシーを作成中..." + aws iam create-policy \ + --policy-name "$POLICY_NAME" \ + --policy-document "$POLICY_DOCUMENT" + + if [ $? -eq 0 ]; then + print_success "IAMポリシーが作成されました: $POLICY_NAME" + else + # 作成に失敗した場合、既に存在する可能性があるので再確認 + RECHECK_RESULT=$(aws iam list-policies --scope Local --query "Policies[?PolicyName=='$POLICY_NAME'].Arn" --output text 2>/dev/null) + if [ $? -eq 0 ] && [ -n "$RECHECK_RESULT" ] && [ "$RECHECK_RESULT" != "None" ]; then + print_success "IAMポリシーは既に存在します: $POLICY_NAME" + else + print_error "IAMポリシーの作成に失敗しました" + exit 1 + fi + fi +fi + +# ポリシーをロールにアタッチ +print_info "ポリシーをロールにアタッチ中..." +aws iam attach-role-policy \ + --role-name "$ROLE_NAME" \ + --policy-arn "arn:aws:iam::$AWS_ACCOUNT_ID:policy/$POLICY_NAME" +print_success "ポリシーがロールにアタッチされました" + +# 10. GitHub Secretsの自動登録 +if [ "$GITHUB_CLI_AVAILABLE" = true ]; then + print_info "GitHub Secretsの自動登録について確認します" + read -p "GitHub Secretsを自動登録しますか? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + print_info "GitHub Secretsの自動登録中..." + + # Repository Secretsの登録(機密情報) + print_info "=== Repository Secretsの登録 ===" + + # 環境別AWS_ROLE_ARNの登録 + AWS_ROLE_ARN="arn:aws:iam::$AWS_ACCOUNT_ID:role/$ROLE_NAME" + if gh secret set "$SECRET_NAME" --body "$AWS_ROLE_ARN" &> /dev/null; then + print_success "$SECRET_NAMEがRepository Secretsに登録されました" + else + print_warning "$SECRET_NAMEの登録に失敗しました" + fi + + # S3_BUCKETの登録 + if gh secret set S3_BUCKET --body "$S3_BUCKET" &> /dev/null; then + print_success "S3_BUCKETがRepository Secretsに登録されました" + else + print_warning "S3_BUCKETの登録に失敗しました" + fi + + # Repository Variablesの登録(非機密情報) + print_info "=== Repository Variablesの登録 ===" + + # AWS_REGIONの登録 + if gh variable set AWS_REGION --body "$AWS_REGION" &> /dev/null; then + print_success "AWS_REGIONがRepository Variablesに登録されました" + else + print_warning "AWS_REGIONの登録に失敗しました" + fi + + # PROJECT_NAMEの登録 + if gh variable set PROJECT_NAME --body "$PROJECT_NAME" &> /dev/null; then + print_success "PROJECT_NAMEがRepository Variablesに登録されました" + else + print_warning "PROJECT_NAMEの登録に失敗しました" + fi + else + print_info "GitHub Secretsの自動登録をスキップしました" + fi +else + print_warning "GitHub CLIが利用できないため、手動でGitHub Secretsを設定してください" +fi + +# 11. 結果の表示 +print_success "設定が完了しました!" +echo "" +echo "=== 設定情報 ===" +echo "AWSアカウントID: $AWS_ACCOUNT_ID" +echo "GitHubユーザー名: $GITHUB_USERNAME" +echo "GitHubリポジトリ名: $GITHUB_REPO_NAME" +echo "IAMロール名: $ROLE_NAME" +echo "IAMロールARN: arn:aws:iam::$AWS_ACCOUNT_ID:role/$ROLE_NAME" +echo "" + +if [ "$GITHUB_CLI_AVAILABLE" = true ]; then + print_success "GitHub SecretsとVariablesが自動登録されました" + echo "登録されたRepository Secrets:" + echo "- $SECRET_NAME" + echo "- S3_BUCKET" + echo "登録されたRepository Variables:" + echo "- AWS_REGION" + echo "- PROJECT_NAME" +else + echo "手動でGitHubに以下を設定してください:" + echo "" + echo "Repository Secrets:" + echo "Name: $SECRET_NAME" + echo "Value: arn:aws:iam::$AWS_ACCOUNT_ID:role/$ROLE_NAME" + echo "Name: S3_BUCKET" + echo "Value: $S3_BUCKET" + echo "" + echo "Repository Variables:" + echo "Name: AWS_REGION" + echo "Value: $AWS_REGION" + echo "Name: PROJECT_NAME" + echo "Value: $PROJECT_NAME" +fi \ No newline at end of file diff --git a/deploy-env.ps1 b/deploy-env.ps1 new file mode 100644 index 0000000..1ecae91 --- /dev/null +++ b/deploy-env.ps1 @@ -0,0 +1,96 @@ +# 環境別デプロイスクリプト (PowerShell) +# 使用方法: .\deploy-env.ps1 [development|production] [aws-profile] + +param( + [Parameter(Mandatory=$false)] + [ValidateSet("development", "production")] + [string]$Environment = "development", + + [Parameter(Mandatory=$false)] + [string]$AwsProfile = "" +) + +# 色付きメッセージ関数 +function Write-Info { + param([string]$Message) + Write-Host "[INFO] $Message" -ForegroundColor Blue +} + +function Write-Success { + param([string]$Message) + Write-Host "[SUCCESS] $Message" -ForegroundColor Green +} + +function Write-Warning { + param([string]$Message) + Write-Host "[WARNING] $Message" -ForegroundColor Yellow +} + +function Write-Error { + param([string]$Message) + Write-Host "[ERROR] $Message" -ForegroundColor Red +} + +# 環境の確認 +Write-Info "環境: $Environment" +if ($AwsProfile) { + Write-Info "AWS Profile: $AwsProfile" + $env:AWS_PROFILE = $AwsProfile +} + +# スタック名の設定 +if ($Environment -eq "production") { + $StackName = "lambda-framework-prod" + Write-Info "本番環境にデプロイします" +} else { + $StackName = "lambda-framework-dev" + Write-Info "開発環境にデプロイします" +} + +Write-Info "スタック名: $StackName" + +# SAMビルド +Write-Info "SAMビルドを実行中..." +try { + sam build + if ($LASTEXITCODE -eq 0) { + Write-Success "SAMビルドが完了しました" + } else { + throw "SAMビルドに失敗しました" + } +} catch { + Write-Error "SAMビルド中にエラーが発生しました: $_" + exit 1 +} + +# SAMデプロイ +Write-Info "SAMデプロイを実行中..." +try { + if ($AwsProfile) { + sam deploy ` + --config-env $Environment ` + --stack-name $StackName ` + --no-confirm-changeset ` + --no-fail-on-empty-changeset ` + --parameter-overrides "Environment=$Environment" ` + --profile $AwsProfile + } else { + sam deploy ` + --config-env $Environment ` + --stack-name $StackName ` + --no-confirm-changeset ` + --no-fail-on-empty-changeset ` + --parameter-overrides "Environment=$Environment" + } + + if ($LASTEXITCODE -eq 0) { + Write-Success "デプロイが完了しました!" + Write-Info "スタック名: $StackName" + Write-Info "環境: $Environment" + } else { + throw "SAMデプロイに失敗しました" + } +} catch { + Write-Error "SAMデプロイ中にエラーが発生しました: $_" + exit 1 +} \ No newline at end of file diff --git a/deploy-env.sh b/deploy-env.sh new file mode 100644 index 0000000..8e86868 --- /dev/null +++ b/deploy-env.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# 環境別デプロイスクリプト +# 使用方法: ./deploy-env.sh [development|production] [aws-profile] + +set -e + +# 色付きメッセージ関数 +print_info() { + echo -e "\033[34m[INFO]\033[0m $1" +} + +print_success() { + echo -e "\033[32m[SUCCESS]\033[0m $1" +} + +print_warning() { + echo -e "\033[33m[WARNING]\033[0m $1" +} + +print_error() { + echo -e "\033[31m[ERROR]\033[0m $1" +} + +# 環境の確認 +ENVIRONMENT=${1:-development} +AWS_PROFILE=${2:-} + +if [[ "$ENVIRONMENT" != "development" && "$ENVIRONMENT" != "production" ]]; then + print_error "無効な環境です。development または production を指定してください。" + echo "使用方法: $0 [development|production] [aws-profile]" + exit 1 +fi + +print_info "環境: $ENVIRONMENT" +if [[ -n "$AWS_PROFILE" ]]; then + print_info "AWS Profile: $AWS_PROFILE" + export AWS_PROFILE="$AWS_PROFILE" +fi + +# スタック名の設定 +if [[ "$ENVIRONMENT" == "production" ]]; then + STACK_NAME="lambda-framework-prod" + print_info "本番環境にデプロイします" +else + STACK_NAME="lambda-framework-dev" + print_info "開発環境にデプロイします" +fi + +print_info "スタック名: $STACK_NAME" + +# SAMビルド +print_info "SAMビルドを実行中..." +sam build + +# SAMデプロイ +print_info "SAMデプロイを実行中..." +if [[ -n "$AWS_PROFILE" ]]; then + sam deploy \ + --config-env $ENVIRONMENT \ + --stack-name $STACK_NAME \ + --no-confirm-changeset \ + --no-fail-on-empty-changeset \ + --parameter-overrides Environment=$ENVIRONMENT \ + --profile $AWS_PROFILE +else + sam deploy \ + --config-env $ENVIRONMENT \ + --stack-name $STACK_NAME \ + --no-confirm-changeset \ + --no-fail-on-empty-changeset \ + --parameter-overrides Environment=$ENVIRONMENT +fi + +print_success "デプロイが完了しました!" +print_info "スタック名: $STACK_NAME" +print_info "環境: $ENVIRONMENT" \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index d72e7b0..e517d09 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ awslambdaric +py-rpds jsonschema jsonpath-ng diff --git a/samconfig.toml b/samconfig.toml new file mode 100644 index 0000000..25d9f75 --- /dev/null +++ b/samconfig.toml @@ -0,0 +1,34 @@ +version = 0.1 + +[default] +[default.deploy] +[default.deploy.parameters] +stack_name = "lambda-framework-prod" +s3_bucket = "cn-seba-aws-sam-cli-managed-default-samclisourcebucket" +region = "ap-northeast-1" +confirm_changeset = false +capabilities = "CAPABILITY_IAM" +parameter_overrides = "ProjectName=LambdaFramework Environment=production" +image_repositories = [] + +[development] +[development.deploy] +[development.deploy.parameters] +stack_name = "lambda-framework-dev" +s3_bucket = "cn-seba-aws-sam-cli-managed-default-samclisourcebucket" +region = "ap-northeast-1" +confirm_changeset = false +capabilities = "CAPABILITY_IAM" +parameter_overrides = "ProjectName=LambdaFramework Environment=development" +image_repositories = [] + +[production] +[production.deploy] +[production.deploy.parameters] +stack_name = "lambda-framework-prod" +s3_bucket = "cn-seba-aws-sam-cli-managed-default-samclisourcebucket" +region = "ap-northeast-1" +confirm_changeset = false +capabilities = "CAPABILITY_IAM" +parameter_overrides = "ProjectName=LambdaFramework Environment=production" +image_repositories = [] \ No newline at end of file diff --git a/template.yaml b/template.yaml index 97d3744..e7c176e 100644 --- a/template.yaml +++ b/template.yaml @@ -1,18 +1,32 @@ AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 + +Parameters: + Environment: + Type: String + Default: development + AllowedValues: + - development + - production + Description: Environment name + Resources: LambdaFramework: Type: AWS::Serverless::LayerVersion Properties: - LayerName: LambdaFramework - Description: Safe retry and stop framework - ContentUri: lib + LayerName: !Sub "${PROJECT_NAME}-${Environment}" + Description: !Sub "Safe retry and stop framework - ${Environment}" + ContentUri: LambdaFramework RetentionPolicy: Retain CompatibleRuntimes: - python3.9 - python3.10 + Outputs: - LambdaFramework: - Value: !Ref LambdaFramework - Export: - Name: Layer-LambdaFramework + LambdaFramework: + Value: !Ref LambdaFramework + Export: + Name: !Sub "Layer-${PROJECT_NAME}-${Environment}" + Environment: + Value: !Ref Environment + Description: Deployed environment From 29e82bacd652dcdefe3a12e9e0ecd4cb4d38bd5a Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 09:58:38 +0900 Subject: [PATCH 02/21] fix: Normalize line endings in template.yaml --- template.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/template.yaml b/template.yaml index e7c176e..6227a62 100644 --- a/template.yaml +++ b/template.yaml @@ -1,3 +1,4 @@ + AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 From 23ea81bf3ee5c74b88e4f889a2b02ef935900c1d Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 10:41:47 +0900 Subject: [PATCH 03/21] fix: Resolve GitHub Actions matrix strategy error - Remove problematic strategy.matrix configuration - Use conditional logic based on github.ref instead - Simplify deployment configuration for main/deploy branches - Fix 'Unexpected value include' error in workflow --- .github/workflows/deploy.yml | 53 +++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 12002d0..2db5a1a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -18,24 +18,6 @@ jobs: deploy: runs-on: ubuntu-latest - # ブランチに基づいてデプロイ設定を決定 - strategy: - matrix: - branch: [main, deploy] - include: - - branch: main - stack_name: lambda-framework-prod - s3_bucket: cn-seba-aws-sam-cli-managed-default-samclisourcebucket - environment: production - aws_role_arn: ${{ secrets.AWS_ROLE_ARN_PROD }} - aws_region: ap-northeast-1 - - branch: deploy - stack_name: lambda-framework-dev - s3_bucket: cn-seba-aws-sam-cli-managed-default-samclisourcebucket - environment: development - aws_role_arn: ${{ secrets.AWS_ROLE_ARN_DEV }} - aws_region: ap-northeast-1 - steps: - name: Checkout code uses: actions/checkout@v4 @@ -57,23 +39,44 @@ jobs: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: - role-to-assume: ${{ matrix.aws_role_arn }} - aws-region: ${{ matrix.aws_region }} + role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_ARN_PROD || secrets.AWS_ROLE_ARN_DEV }} + aws-region: ${{ env.AWS_REGION }} - name: Deploy with SAM run: | + # ブランチに基づいて環境設定を決定 + if [ "${{ github.ref }}" = "refs/heads/main" ]; then + STACK_NAME="lambda-framework-prod" + ENVIRONMENT="production" + else + STACK_NAME="lambda-framework-dev" + ENVIRONMENT="development" + fi + + echo "Deploying to environment: $ENVIRONMENT" + echo "Stack name: $STACK_NAME" + sam build sam deploy --no-confirm-changeset --no-fail-on-empty-changeset \ - --stack-name ${{ matrix.stack_name }} \ - --s3-bucket ${{ matrix.s3_bucket }} \ - --parameter-overrides ProjectName=${{ env.PROJECT_NAME }} Environment=${{ matrix.environment }} + --stack-name $STACK_NAME \ + --s3-bucket cn-seba-aws-sam-cli-managed-default-samclisourcebucket \ + --parameter-overrides ProjectName=${{ env.PROJECT_NAME }} Environment=$ENVIRONMENT env: SAM_CLI_TELEMETRY: 0 - name: Deploy status if: always() run: | + # ブランチに基づいて環境設定を決定 + if [ "${{ github.ref }}" = "refs/heads/main" ]; then + STACK_NAME="lambda-framework-prod" + ENVIRONMENT="production" + else + STACK_NAME="lambda-framework-dev" + ENVIRONMENT="development" + fi + echo "Deployment completed for branch: ${{ github.ref }}" - echo "Stack name: ${{ matrix.stack_name }}" - echo "Environment: ${{ matrix.environment }}" + echo "Stack name: $STACK_NAME" + echo "Environment: $ENVIRONMENT" echo "Commit: ${{ github.sha }}" \ No newline at end of file From 17ed06d9fc484f5763480f4a422610271305adbd Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 10:47:35 +0900 Subject: [PATCH 04/21] fix: Correct package name from py-rpds to rpds-py - Fix PIP installation error in GitHub Actions - py-rpds package does not exist, correct name is rpds-py - rpds-py is compatible with Python 3.11 - This resolves the 'Could not find a version that satisfies the requirement' error --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e517d09..3246dcf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ awslambdaric -py-rpds +rpds-py jsonschema jsonpath-ng From 07eda8c2a5f14c5a50bd83b62576d4af68efbc0b Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 10:49:31 +0900 Subject: [PATCH 05/21] fix: Resolve AWS Region error in GitHub Actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move sam validate after AWS credentials configuration - Add explicit AWS_REGION environment variable to SAM steps - Add AWS identity verification for debugging - Fix 'AWS Region was not found' error in SAM execution - Ensure proper execution order: credentials → validate → deploy --- .github/workflows/deploy.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2db5a1a..2f52b93 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,16 +32,21 @@ jobs: python -m pip install --upgrade pip pip install -r requirements.txt - - name: Validate SAM template - run: | - sam validate - - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_ARN_PROD || secrets.AWS_ROLE_ARN_DEV }} aws-region: ${{ env.AWS_REGION }} + - name: Validate SAM template + run: | + # AWS認証情報の確認 + aws sts get-caller-identity + echo "AWS Region: $AWS_REGION" + sam validate + env: + AWS_REGION: ${{ env.AWS_REGION }} + - name: Deploy with SAM run: | # ブランチに基づいて環境設定を決定 @@ -55,6 +60,7 @@ jobs: echo "Deploying to environment: $ENVIRONMENT" echo "Stack name: $STACK_NAME" + echo "AWS Region: $AWS_REGION" sam build sam deploy --no-confirm-changeset --no-fail-on-empty-changeset \ @@ -62,6 +68,7 @@ jobs: --s3-bucket cn-seba-aws-sam-cli-managed-default-samclisourcebucket \ --parameter-overrides ProjectName=${{ env.PROJECT_NAME }} Environment=$ENVIRONMENT env: + AWS_REGION: ${{ env.AWS_REGION }} SAM_CLI_TELEMETRY: 0 - name: Deploy status From 030644201be0d4c41b1529bb650a82c7bd7650f7 Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 11:09:30 +0900 Subject: [PATCH 06/21] docs: Update GitHub Secrets setup guide with OIDC troubleshooting - Add detailed OIDC provider creation steps - Add IAM role trust policy examples - Add troubleshooting section for 'Request ARN is invalid' error - Include verification commands for OIDC and IAM setup - Add step-by-step setup instructions for multi-account deployment --- GITHUB_SECRETS_SETUP.md | 211 +++++++++++++++++++++++++++++++--------- 1 file changed, 166 insertions(+), 45 deletions(-) diff --git a/GITHUB_SECRETS_SETUP.md b/GITHUB_SECRETS_SETUP.md index 0a993bb..a562a50 100644 --- a/GITHUB_SECRETS_SETUP.md +++ b/GITHUB_SECRETS_SETUP.md @@ -1,37 +1,96 @@ -# GitHub Secrets設定ガイド +# GitHub Secrets Setup Guide + +## 概要 +このドキュメントでは、GitHub ActionsでAWS CloudFormationにデプロイするために必要なGitHub SecretsとIAMロールの設定手順を説明します。 ## 必要なGitHub Secrets -### 開発環境用 -- **`AWS_ROLE_ARN_DEV`**: 開発環境用のIAMロールARN - - 例: `arn:aws:iam::123456789012:role/LambdaFramework-github-actions-role-dev` +### 1. AWS_ROLE_ARN_DEV (開発環境用) +- **説明**: 開発環境(deployブランチ)で使用するIAMロールのARN +- **例**: `arn:aws:iam::123456789012:role/LambdaFramework-github-actions-role` -### 本番環境用 -- **`AWS_ROLE_ARN_PROD`**: 本番環境用のIAMロールARN - - 例: `arn:aws:iam::987654321098:role/LambdaFramework-github-actions-role-prod` +### 2. AWS_ROLE_ARN_PROD (本番環境用) +- **説明**: 本番環境(mainブランチ)で使用するIAMロールのARN +- **例**: `arn:aws:iam::123456789012:role/LambdaFramework-github-actions-role` -## 設定手順 +## IAMロールとOIDCプロバイダーの設定 -### 1. GitHub Secretsの設定 +### 1. OIDCプロバイダーの作成 -1. GitHubリポジトリの **Settings** → **Secrets and variables** → **Actions** に移動 -2. **New repository secret** をクリック -3. 以下のSecretsを追加: +#### 開発環境用AWSアカウント +```bash +# OIDCプロバイダーの作成 +aws iam create-open-id-connect-provider \ + --url https://token.actions.githubusercontent.com \ + --client-id-list sts.amazonaws.com \ + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 +# 作成されたOIDCプロバイダーのARNを確認 +aws iam list-open-id-connect-providers ``` -Name: AWS_ROLE_ARN_DEV -Value: arn:aws:iam:::role/ -Name: AWS_ROLE_ARN_PROD -Value: arn:aws:iam:::role/ +#### 本番環境用AWSアカウント +```bash +# OIDCプロバイダーの作成 +aws iam create-open-id-connect-provider \ + --url https://token.actions.githubusercontent.com \ + --client-id-list sts.amazonaws.com \ + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 + +# 作成されたOIDCプロバイダーのARNを確認 +aws iam list-open-id-connect-providers ``` ### 2. IAMロールの作成 -各AWSアカウントで以下のIAMロールを作成: - #### 開発環境用IAMロール ```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam::YOUR_DEV_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", + "token.actions.githubusercontent.com:sub": "repo:cloudnative-co/python-lambda-frame:ref:refs/heads/deploy" + } + } + } + ] +} +``` + +#### 本番環境用IAMロール +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam::YOUR_PROD_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", + "token.actions.githubusercontent.com:sub": "repo:cloudnative-co/python-lambda-frame:ref:refs/heads/main" + } + } + } + ] +} +``` + +### 3. IAMポリシーの作成 + +#### 開発環境用IAMポリシー +```json { "Version": "2012-10-17", "Statement": [ @@ -39,8 +98,8 @@ Value: arn:aws:iam:::role/ "Effect": "Allow", "Action": [ "cloudformation:*", - "lambda:*", "s3:*", + "lambda:*", "iam:*", "logs:*" ], @@ -50,7 +109,7 @@ Value: arn:aws:iam:::role/ } ``` -#### 本番環境用IAMロール +#### 本番環境用IAMポリシー ```json { "Version": "2012-10-17", @@ -59,8 +118,8 @@ Value: arn:aws:iam:::role/ "Effect": "Allow", "Action": [ "cloudformation:*", - "lambda:*", "s3:*", + "lambda:*", "iam:*", "logs:*" ], @@ -70,53 +129,115 @@ Value: arn:aws:iam:::role/ } ``` -### 3. OIDCプロバイダーの設定 +## トラブルシューティング + +### 1. "Request ARN is invalid" エラーの解決 + +#### A. OIDCプロバイダーの確認 +```bash +# OIDCプロバイダーが存在するか確認 +aws iam list-open-id-connect-providers + +# 特定のOIDCプロバイダーの詳細を確認 +aws iam get-open-id-connect-provider --open-id-connect-provider-arn arn:aws:iam::YOUR_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com +``` + +#### B. IAMロールの信頼関係の確認 +```bash +# IAMロールの詳細を確認 +aws iam get-role --role-name LambdaFramework-github-actions-role + +# 信頼関係(Trust Policy)を確認 +aws iam get-role-policy --role-name LambdaFramework-github-actions-role --policy-name trust-policy +``` + +#### C. 正しいロールARNの確認 +```bash +# 利用可能なIAMロールを一覧表示 +aws iam list-roles --query 'Roles[?contains(RoleName, `LambdaFramework`)].RoleName' --output table +``` + +### 2. よくある問題と解決方法 + +#### A. OIDCプロバイダーが存在しない +```bash +# OIDCプロバイダーを作成 +aws iam create-open-id-connect-provider \ + --url https://token.actions.githubusercontent.com \ + --client-id-list sts.amazonaws.com \ + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 +``` + +#### B. 信頼関係が正しくない +- IAMロールの信頼関係で、正しいOIDCプロバイダーARNを指定 +- 正しいリポジトリ名とブランチ名を指定 + +#### C. GitHub Secretsが設定されていない +- GitHubリポジトリのSettings → Secrets and variables → Actions +- `AWS_ROLE_ARN_DEV`と`AWS_ROLE_ARN_PROD`を設定 -各AWSアカウントでGitHub Actions用のOIDCプロバイダーを設定: +## 設定手順 +### 1. AWS CLIでOIDCプロバイダーを作成 ```bash -# 開発環境 +# 開発環境用 aws iam create-open-id-connect-provider \ --url https://token.actions.githubusercontent.com \ --client-id-list sts.amazonaws.com \ --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 -# 本番環境 +# 本番環境用 aws iam create-open-id-connect-provider \ --url https://token.actions.githubusercontent.com \ --client-id-list sts.amazonaws.com \ --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 ``` -## デプロイ先の確認 +### 2. IAMロールを作成 +```bash +# 開発環境用ロール +aws iam create-role --role-name LambdaFramework-github-actions-role --assume-role-policy-document file://trust-policy-dev.json + +# 本番環境用ロール +aws iam create-role --role-name LambdaFramework-github-actions-role --assume-role-policy-document file://trust-policy-prod.json +``` + +### 3. IAMポリシーをアタッチ +```bash +# 開発環境用ポリシー +aws iam put-role-policy --role-name LambdaFramework-github-actions-role --policy-name LambdaFramework-github-actions-policy --policy-document file://policy-dev.json + +# 本番環境用ポリシー +aws iam put-role-policy --role-name LambdaFramework-github-actions-role --policy-name LambdaFramework-github-actions-policy --policy-document file://policy-prod.json +``` + +### 4. GitHub Secretsを設定 +1. GitHubリポジトリにアクセス +2. Settings → Secrets and variables → Actions +3. New repository secretをクリック +4. `AWS_ROLE_ARN_DEV`と`AWS_ROLE_ARN_PROD`を設定 + +## デプロイ環境マッピング -| ブランチ | AWSアカウント | スタック名 | 環境 | -|---------|-------------|-----------|------| -| `main` | 本番アカウント | `lambda-framework-prod` | production | -| `deploy` | 開発アカウント | `lambda-framework-dev` | development | +| ブランチ | 環境 | AWSロール | GitHub Secret | +|---------|------|-----------|---------------| +| main | production | LambdaFramework-github-actions-role | AWS_ROLE_ARN_PROD | +| deploy | development | LambdaFramework-github-actions-role | AWS_ROLE_ARN_DEV | -## ローカルデプロイ +## ローカルデプロイコマンド -### Bash版 +### 開発環境 ```bash -# 開発環境(デフォルトAWS Profile) ./deploy-env.sh development +``` -# 開発環境(指定AWS Profile) -./deploy-env.sh development dev-profile - -# 本番環境(指定AWS Profile) -./deploy-env.sh production prod-profile +### 本番環境 +```bash +./deploy-env.sh production ``` ### PowerShell版 ```powershell -# 開発環境(デフォルトAWS Profile) .\deploy-env.ps1 development - -# 開発環境(指定AWS Profile) -.\deploy-env.ps1 development dev-profile - -# 本番環境(指定AWS Profile) -.\deploy-env.ps1 production prod-profile +.\deploy-env.ps1 production ``` \ No newline at end of file From 3e9e52997c8141c2de98759fefaf503910507c9a Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 11:18:32 +0900 Subject: [PATCH 07/21] fix: Add AWS account ID validation and debug info for GitHub Secrets - Add validation to ensure AWS account ID is properly retrieved - Add debug information showing the exact ARN being registered - Improve error handling for AWS account ID retrieval - Add manual setup instructions when GitHub Secrets registration fails - Fix potential issue where account ID might be missing from ARN --- create_role.ps1 | 6 ++++++ create_role.sh | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/create_role.ps1 b/create_role.ps1 index 4c1df05..35de3cd 100644 --- a/create_role.ps1 +++ b/create_role.ps1 @@ -917,6 +917,12 @@ if (-not $GITHUB_CLI_WORKING) { # 6. AWSアカウントIDの取得 Write-Info "AWSアカウントIDの取得中..." $AWS_ACCOUNT_ID = aws sts get-caller-identity --query Account --output text 2>$null +if (-not $AWS_ACCOUNT_ID -or $AWS_ACCOUNT_ID -eq "None") { + Write-Error "AWSアカウントIDの取得に失敗しました" + Write-Info "AWS認証情報を確認してください" + aws sts get-caller-identity + exit 1 +} Write-Success "AWSアカウントID: $AWS_ACCOUNT_ID" # AWSリージョンの確認 diff --git a/create_role.sh b/create_role.sh index 1a90bf2..abb4b6e 100644 --- a/create_role.sh +++ b/create_role.sh @@ -941,6 +941,12 @@ fi # 6. AWSアカウントIDの取得 print_info "AWSアカウントIDの取得中..." AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +if [ -z "$AWS_ACCOUNT_ID" ] || [ "$AWS_ACCOUNT_ID" = "None" ]; then + print_error "AWSアカウントIDの取得に失敗しました" + print_info "AWS認証情報を確認してください" + aws sts get-caller-identity + exit 1 +fi print_success "AWSアカウントID: $AWS_ACCOUNT_ID" # AWSリージョンの確認 @@ -1148,10 +1154,14 @@ if [ "$GITHUB_CLI_AVAILABLE" = true ]; then # 環境別AWS_ROLE_ARNの登録 AWS_ROLE_ARN="arn:aws:iam::$AWS_ACCOUNT_ID:role/$ROLE_NAME" + print_info "登録するARN: $AWS_ROLE_ARN" if gh secret set "$SECRET_NAME" --body "$AWS_ROLE_ARN" &> /dev/null; then print_success "$SECRET_NAMEがRepository Secretsに登録されました" else print_warning "$SECRET_NAMEの登録に失敗しました" + print_info "手動でGitHub Secretsに設定してください:" + print_info "Name: $SECRET_NAME" + print_info "Value: $AWS_ROLE_ARN" fi # S3_BUCKETの登録 From 2bc4c1525892f55d87822677cbace0bbec7b7165 Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 11:24:41 +0900 Subject: [PATCH 08/21] fix: Resolve PowerShell variable expansion issue in create_role.ps1 - Fix variable expansion in ARN generation - Use PowerShell subexpression syntax for reliable variable expansion - Add debug information to show AWS account ID and role name - Fix OIDC provider ARN generation with proper variable expansion - Ensure ARN format includes account ID: arn:aws:iam:ACCOUNT_ID:role/ROLE_NAME --- create_role.ps1 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/create_role.ps1 b/create_role.ps1 index 35de3cd..0ba509a 100644 --- a/create_role.ps1 +++ b/create_role.ps1 @@ -951,7 +951,7 @@ Write-Info "既存のOIDCプロバイダーを取得中..." $OIDC_PROVIDERS = aws iam list-open-id-connect-providers --query 'OpenIDConnectProviderList[].Arn' --output text 2>$null # GitHub Actions用のOIDCプロバイダーARN -$GITHUB_OIDC_ARN = "arn:aws:iam:$AWS_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com" +$GITHUB_OIDC_ARN = "arn:aws:iam:$($AWS_ACCOUNT_ID):oidc-provider/token.actions.githubusercontent.com" # 選択肢を準備 Write-Host "" @@ -1203,7 +1203,12 @@ if ($GITHUB_CLI_AVAILABLE) { Write-Info "=== Repository Secretsの登録 ===" # 環境別AWS_ROLE_ARNの登録 - $AWS_ROLE_ARN = "arn:aws:iam:$AWS_ACCOUNT_ID:role/$ROLE_NAME" + Write-Info "AWSアカウントID: $AWS_ACCOUNT_ID" + Write-Info "IAMロール名: $ROLE_NAME" + + # PowerShellの文字列展開を確実にする + $AWS_ROLE_ARN = "arn:aws:iam:$($AWS_ACCOUNT_ID):role/$($ROLE_NAME)" + Write-Info "生成されるARN: $AWS_ROLE_ARN" Write-Info "$SECRET_NAMEをRepository Secretsに登録中: $AWS_ROLE_ARN" $result = gh secret set $SECRET_NAME --body $AWS_ROLE_ARN 2>&1 if ($LASTEXITCODE -eq 0) { @@ -1257,7 +1262,7 @@ Write-Host "AWSアカウントID: $AWS_ACCOUNT_ID" Write-Host "GitHubユーザー名: $GITHUB_USERNAME" Write-Host "GitHubリポジトリ名: $GITHUB_REPO_NAME" Write-Host "IAMロール名: $ROLE_NAME" -Write-Host "IAMロールARN: arn:aws:iam:$AWS_ACCOUNT_ID:role/$ROLE_NAME" +Write-Host "IAMロールARN: arn:aws:iam:$($AWS_ACCOUNT_ID):role/$($ROLE_NAME)" Write-Host "" if ($GITHUB_CLI_AVAILABLE) { @@ -1273,7 +1278,7 @@ if ($GITHUB_CLI_AVAILABLE) { Write-Host "" Write-Host "Repository Secrets:" -ForegroundColor Cyan Write-Host "Name: $SECRET_NAME" - Write-Host "Value: arn:aws:iam:$AWS_ACCOUNT_ID:role/$ROLE_NAME" + Write-Host "Value: arn:aws:iam:$($AWS_ACCOUNT_ID):role/$($ROLE_NAME)" Write-Host "Name: S3_BUCKET" Write-Host "Value: $S3_BUCKET" Write-Host "" From a6701cc7f7831a2f291c2f5ab6ab25db082589df Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 11:32:19 +0900 Subject: [PATCH 09/21] fix: Update IAM Role Trust Policy to allow both main and deploy branches - Change from StringEquals to StringLike for sub condition - Allow both main and deploy branches in OIDC trust policy - Fix 'Request ARN is invalid' error in GitHub Actions - Update condition to use array format for multiple branch patterns - Ensure proper OIDC authentication for multi-branch deployment --- create_role.ps1 | 9 +++++++-- create_role.sh | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/create_role.ps1 b/create_role.ps1 index 0ba509a..b1dd065 100644 --- a/create_role.ps1 +++ b/create_role.ps1 @@ -1051,8 +1051,13 @@ $TRUST_POLICY = @" "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { - "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", - "token.actions.githubusercontent.com:sub": "repo:$GITHUB_USERNAME/$GITHUB_REPO_NAME:ref:refs/heads/deploy" + "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" + }, + "StringLike": { + "token.actions.githubusercontent.com:sub": [ + "repo:$GITHUB_USERNAME/$GITHUB_REPO_NAME:ref:refs/heads/main", + "repo:$GITHUB_USERNAME/$GITHUB_REPO_NAME:ref:refs/heads/deploy" + ] } } } diff --git a/create_role.sh b/create_role.sh index abb4b6e..64fabe4 100644 --- a/create_role.sh +++ b/create_role.sh @@ -1054,8 +1054,13 @@ TRUST_POLICY=$(cat < Date: Thu, 31 Jul 2025 12:04:50 +0900 Subject: [PATCH 10/21] fix: Remove hardcoded S3 bucket name in GitHub Actions workflow - Replace hardcoded S3 bucket name with environment-specific variables - Add S3_BUCKET_DEV and S3_BUCKET_PROD variables for multi-environment deployment - Update create_role scripts to register environment-specific S3 bucket variables - Use GitHub Variables instead of hardcoded values for better flexibility - Support different S3 buckets for development and production environments --- .github/workflows/deploy.yml | 5 ++++- create_role.ps1 | 23 +++++++++++++++++++++++ create_role.sh | 19 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2f52b93..7f3c819 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -53,19 +53,22 @@ jobs: if [ "${{ github.ref }}" = "refs/heads/main" ]; then STACK_NAME="lambda-framework-prod" ENVIRONMENT="production" + S3_BUCKET="${{ vars.S3_BUCKET_PROD }}" else STACK_NAME="lambda-framework-dev" ENVIRONMENT="development" + S3_BUCKET="${{ vars.S3_BUCKET_DEV }}" fi echo "Deploying to environment: $ENVIRONMENT" echo "Stack name: $STACK_NAME" echo "AWS Region: $AWS_REGION" + echo "S3 Bucket: $S3_BUCKET" sam build sam deploy --no-confirm-changeset --no-fail-on-empty-changeset \ --stack-name $STACK_NAME \ - --s3-bucket cn-seba-aws-sam-cli-managed-default-samclisourcebucket \ + --s3-bucket $S3_BUCKET \ --parameter-overrides ProjectName=${{ env.PROJECT_NAME }} Environment=$ENVIRONMENT env: AWS_REGION: ${{ env.AWS_REGION }} diff --git a/create_role.ps1 b/create_role.ps1 index b1dd065..8cf9eca 100644 --- a/create_role.ps1 +++ b/create_role.ps1 @@ -1251,6 +1251,23 @@ if ($GITHUB_CLI_AVAILABLE) { } else { Write-Warning "PROJECT_NAME の登録に失敗しました: $result" } + + # 環境別S3バケットの登録 + Write-Info "S3_BUCKET_DEVをRepository Variablesに登録中: $S3_BUCKET" + $result = gh variable set S3_BUCKET_DEV --body $S3_BUCKET 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "S3_BUCKET_DEV がRepository Variablesに登録されました" + } else { + Write-Warning "S3_BUCKET_DEV の登録に失敗しました: $result" + } + + Write-Info "S3_BUCKET_PRODをRepository Variablesに登録中: $S3_BUCKET" + $result = gh variable set S3_BUCKET_PROD --body $S3_BUCKET 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-Success "S3_BUCKET_PROD がRepository Variablesに登録されました" + } else { + Write-Warning "S3_BUCKET_PROD の登録に失敗しました: $result" + } } else { Write-Info "GitHub Secretsの自動登録をスキップしました" } @@ -1278,6 +1295,8 @@ if ($GITHUB_CLI_AVAILABLE) { Write-Host "登録されたRepository Variables:" -ForegroundColor Yellow Write-Host "- AWS_REGION" Write-Host "- PROJECT_NAME" + Write-Host "- S3_BUCKET_DEV" + Write-Host "- S3_BUCKET_PROD" } else { Write-Host "手動でGitHubに以下を設定してください:" -ForegroundColor Yellow Write-Host "" @@ -1292,4 +1311,8 @@ if ($GITHUB_CLI_AVAILABLE) { Write-Host "Value: $AWS_REGION" Write-Host "Name: PROJECT_NAME" Write-Host "Value: $PROJECT_NAME" + Write-Host "Name: S3_BUCKET_DEV" + Write-Host "Value: $S3_BUCKET" + Write-Host "Name: S3_BUCKET_PROD" + Write-Host "Value: $S3_BUCKET" } \ No newline at end of file diff --git a/create_role.sh b/create_role.sh index 64fabe4..411052d 100644 --- a/create_role.sh +++ b/create_role.sh @@ -1192,6 +1192,19 @@ if [ "$GITHUB_CLI_AVAILABLE" = true ]; then else print_warning "PROJECT_NAMEの登録に失敗しました" fi + + # 環境別S3バケットの登録 + if gh variable set S3_BUCKET_DEV --body "$S3_BUCKET" &> /dev/null; then + print_success "S3_BUCKET_DEVがRepository Variablesに登録されました" + else + print_warning "S3_BUCKET_DEVの登録に失敗しました" + fi + + if gh variable set S3_BUCKET_PROD --body "$S3_BUCKET" &> /dev/null; then + print_success "S3_BUCKET_PRODがRepository Variablesに登録されました" + else + print_warning "S3_BUCKET_PRODの登録に失敗しました" + fi else print_info "GitHub Secretsの自動登録をスキップしました" fi @@ -1218,6 +1231,8 @@ if [ "$GITHUB_CLI_AVAILABLE" = true ]; then echo "登録されたRepository Variables:" echo "- AWS_REGION" echo "- PROJECT_NAME" + echo "- S3_BUCKET_DEV" + echo "- S3_BUCKET_PROD" else echo "手動でGitHubに以下を設定してください:" echo "" @@ -1232,4 +1247,8 @@ else echo "Value: $AWS_REGION" echo "Name: PROJECT_NAME" echo "Value: $PROJECT_NAME" + echo "Name: S3_BUCKET_DEV" + echo "Value: $S3_BUCKET" + echo "Name: S3_BUCKET_PROD" + echo "Value: $S3_BUCKET" fi \ No newline at end of file From a3478676cff85db9dbfa34750c354a9ef79658b5 Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 17:34:22 +0900 Subject: [PATCH 11/21] test: Trigger GitHub Actions deployment test - Update README with comprehensive documentation - Test OIDC authentication and multi-environment deployment - Verify GitHub Actions workflow with updated configurations --- README.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 052c993..b7fc62e 100644 --- a/README.md +++ b/README.md @@ -1 +1,36 @@ -# python-lambda-frame \ No newline at end of file +# Python Lambda Framework + +AWS Lambda Layer for Python development with comprehensive schema support. + +## Features + +- **Multi-Service Support**: Comprehensive AWS service schemas +- **Environment Management**: Multi-account deployment support +- **CI/CD Integration**: GitHub Actions with OIDC authentication +- **Flexible Configuration**: Environment-specific S3 buckets and IAM roles + +## Quick Start + +1. **Setup IAM Roles and OIDC**: + ```bash + ./create_role.sh + # or + ./create_role.ps1 + ``` + +2. **Deploy to AWS**: + ```bash + sam build + sam deploy + ``` + +## GitHub Actions + +This project includes automated CI/CD pipeline with: +- Multi-branch deployment (`main` → production, `deploy` → development) +- OIDC authentication for secure AWS access +- Environment-specific configurations + +## Updated: 2025-07-31 + +Latest deployment test with OIDC and multi-environment setup. \ No newline at end of file From 4fb69c2676212b7f95ac6b5b7e505db6007ad8a4 Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 17:37:46 +0900 Subject: [PATCH 12/21] fix: Update production IAM role ARN and retest GitHub Actions --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b7fc62e..097e04c 100644 --- a/README.md +++ b/README.md @@ -33,4 +33,5 @@ This project includes automated CI/CD pipeline with: ## Updated: 2025-07-31 -Latest deployment test with OIDC and multi-environment setup. \ No newline at end of file +Latest deployment test with OIDC and multi-environment setup. +Fixed IAM role ARN configuration for production environment. \ No newline at end of file From a9ad1ce225283c5ee077b7dd39410fc9ec5270d1 Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 17:50:29 +0900 Subject: [PATCH 13/21] debug: Add debug information to GitHub Actions workflow - Add debug step to show current branch and IAM role ARN - Display which secrets are being used - Help identify OIDC authentication issue --- .github/workflows/deploy.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7f3c819..ae62337 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -38,6 +38,13 @@ jobs: role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_ARN_PROD || secrets.AWS_ROLE_ARN_DEV }} aws-region: ${{ env.AWS_REGION }} + - name: Debug AWS Role ARN + run: | + echo "Current branch: ${{ github.ref }}" + echo "Using role ARN: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_ARN_PROD || secrets.AWS_ROLE_ARN_DEV }}" + echo "AWS_ROLE_ARN_DEV exists: ${{ secrets.AWS_ROLE_ARN_DEV != '' }}" + echo "AWS_ROLE_ARN_PROD exists: ${{ secrets.AWS_ROLE_ARN_PROD != '' }}" + - name: Validate SAM template run: | # AWS認証情報の確認 From dc022b18e842145857728dd599689ef92dee8013 Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 17:54:19 +0900 Subject: [PATCH 14/21] fix: Move debug step before AWS credentials configuration --- .github/workflows/deploy.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ae62337..05c931a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,12 +32,6 @@ jobs: python -m pip install --upgrade pip pip install -r requirements.txt - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_ARN_PROD || secrets.AWS_ROLE_ARN_DEV }} - aws-region: ${{ env.AWS_REGION }} - - name: Debug AWS Role ARN run: | echo "Current branch: ${{ github.ref }}" @@ -45,6 +39,12 @@ jobs: echo "AWS_ROLE_ARN_DEV exists: ${{ secrets.AWS_ROLE_ARN_DEV != '' }}" echo "AWS_ROLE_ARN_PROD exists: ${{ secrets.AWS_ROLE_ARN_PROD != '' }}" + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_ARN_PROD || secrets.AWS_ROLE_ARN_DEV }} + aws-region: ${{ env.AWS_REGION }} + - name: Validate SAM template run: | # AWS認証情報の確認 From a8654291f32782deff1bacc2be5c1deecf79b26b Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 17:57:56 +0900 Subject: [PATCH 15/21] debug: Add more detailed debug information for IAM role ARN --- .github/workflows/deploy.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 05c931a..6332f55 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,9 +35,12 @@ jobs: - name: Debug AWS Role ARN run: | echo "Current branch: ${{ github.ref }}" + echo "Branch condition: ${{ github.ref == 'refs/heads/main' }}" echo "Using role ARN: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_ARN_PROD || secrets.AWS_ROLE_ARN_DEV }}" echo "AWS_ROLE_ARN_DEV exists: ${{ secrets.AWS_ROLE_ARN_DEV != '' }}" echo "AWS_ROLE_ARN_PROD exists: ${{ secrets.AWS_ROLE_ARN_PROD != '' }}" + echo "AWS_ROLE_ARN_DEV length: ${{ secrets.AWS_ROLE_ARN_DEV != '' && length(secrets.AWS_ROLE_ARN_DEV) || 0 }}" + echo "AWS_ROLE_ARN_PROD length: ${{ secrets.AWS_ROLE_ARN_PROD != '' && length(secrets.AWS_ROLE_ARN_PROD) || 0 }}" - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 From 9517425efc9be20d4fbe613b7a24d96a1f425412 Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 17:59:25 +0900 Subject: [PATCH 16/21] fix: Remove invalid length() function from GitHub Actions expression --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6332f55..5cfc445 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -39,8 +39,8 @@ jobs: echo "Using role ARN: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_ARN_PROD || secrets.AWS_ROLE_ARN_DEV }}" echo "AWS_ROLE_ARN_DEV exists: ${{ secrets.AWS_ROLE_ARN_DEV != '' }}" echo "AWS_ROLE_ARN_PROD exists: ${{ secrets.AWS_ROLE_ARN_PROD != '' }}" - echo "AWS_ROLE_ARN_DEV length: ${{ secrets.AWS_ROLE_ARN_DEV != '' && length(secrets.AWS_ROLE_ARN_DEV) || 0 }}" - echo "AWS_ROLE_ARN_PROD length: ${{ secrets.AWS_ROLE_ARN_PROD != '' && length(secrets.AWS_ROLE_ARN_PROD) || 0 }}" + echo "AWS_ROLE_ARN_DEV length: ${{ secrets.AWS_ROLE_ARN_DEV != '' && 'non-empty' || 'empty' }}" + echo "AWS_ROLE_ARN_PROD length: ${{ secrets.AWS_ROLE_ARN_PROD != '' && 'non-empty' || 'empty' }}" - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 From f1ac552b4fc15162efb35ceb2b28a001922913ed Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 18:16:19 +0900 Subject: [PATCH 17/21] fix: Correct IAM role ARN format with double colon - Fix IAM role ARN format from 'arn:aws:iam:ACCOUNT_ID:role/ROLE_NAME' - to 'arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME' (double colon) - This was causing 'Request ARN is invalid' error in GitHub Actions - Update PowerShell script to generate correct ARN format --- create_role.ps1 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/create_role.ps1 b/create_role.ps1 index 8cf9eca..801bafc 100644 --- a/create_role.ps1 +++ b/create_role.ps1 @@ -1212,10 +1212,11 @@ if ($GITHUB_CLI_AVAILABLE) { Write-Info "IAMロール名: $ROLE_NAME" # PowerShellの文字列展開を確実にする - $AWS_ROLE_ARN = "arn:aws:iam:$($AWS_ACCOUNT_ID):role/$($ROLE_NAME)" + $AWS_ROLE_ARN = "arn:aws:iam::$($AWS_ACCOUNT_ID):role/$($ROLE_NAME)" Write-Info "生成されるARN: $AWS_ROLE_ARN" Write-Info "$SECRET_NAMEをRepository Secretsに登録中: $AWS_ROLE_ARN" - $result = gh secret set $SECRET_NAME --body $AWS_ROLE_ARN 2>&1 + $result = gh variable set $SECRET_NAME --body $AWS_ROLE_ARN 2>&1 + $result = gh secret set $SECRET_NAME --body $AWS_ROLE_ARN 2>&1 if ($LASTEXITCODE -eq 0) { Write-Success "$SECRET_NAME がRepository Secretsに登録されました" } else { @@ -1284,7 +1285,7 @@ Write-Host "AWSアカウントID: $AWS_ACCOUNT_ID" Write-Host "GitHubユーザー名: $GITHUB_USERNAME" Write-Host "GitHubリポジトリ名: $GITHUB_REPO_NAME" Write-Host "IAMロール名: $ROLE_NAME" -Write-Host "IAMロールARN: arn:aws:iam:$($AWS_ACCOUNT_ID):role/$($ROLE_NAME)" +Write-Host "IAMロールARN: arn:aws:iam::$($AWS_ACCOUNT_ID):role/$($ROLE_NAME)" Write-Host "" if ($GITHUB_CLI_AVAILABLE) { @@ -1302,7 +1303,7 @@ if ($GITHUB_CLI_AVAILABLE) { Write-Host "" Write-Host "Repository Secrets:" -ForegroundColor Cyan Write-Host "Name: $SECRET_NAME" - Write-Host "Value: arn:aws:iam:$($AWS_ACCOUNT_ID):role/$($ROLE_NAME)" + Write-Host "Value: arn:aws:iam::$($AWS_ACCOUNT_ID):role/$($ROLE_NAME)" Write-Host "Name: S3_BUCKET" Write-Host "Value: $S3_BUCKET" Write-Host "" From ff056e83a9fbf8ec0e0e0734f17986e78ced8b2f Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 18:17:20 +0900 Subject: [PATCH 18/21] test: Test GitHub Actions with corrected IAM role ARN format --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 097e04c..00e7dd3 100644 --- a/README.md +++ b/README.md @@ -34,4 +34,5 @@ This project includes automated CI/CD pipeline with: ## Updated: 2025-07-31 Latest deployment test with OIDC and multi-environment setup. -Fixed IAM role ARN configuration for production environment. \ No newline at end of file +Fixed IAM role ARN configuration for production environment. +Fixed IAM role ARN format with double colon (::) for correct AWS format. \ No newline at end of file From 87e5ed398aa7369358359b76f600bcd5f33ce9c5 Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 18:28:19 +0900 Subject: [PATCH 19/21] fix: Update IAM policy with specific S3 permissions for SAM deployment - Add specific S3 permissions for SAM deployment bucket - Include s3:GetObject, s3:PutObject, s3:DeleteObject, s3:ListBucket - Add s3:GetBucketLocation, s3:GetObjectVersion, s3:PutObjectAcl - Allow s3:CreateBucket, s3:DeleteBucket, s3:ListAllMyBuckets for bucket management - Target specific S3 bucket: cn-seba-aws-sam-cli-managed-default-samclisourcebucket --- create_role.ps1 | 26 +++++++++++++++++++++++++- create_role.sh | 26 +++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/create_role.ps1 b/create_role.ps1 index 801bafc..b95318e 100644 --- a/create_role.ps1 +++ b/create_role.ps1 @@ -1111,12 +1111,36 @@ $POLICY_DOCUMENT = @" "Effect": "Allow", "Action": [ "cloudformation:*", - "s3:*", "lambda:*", "iam:*", "logs:*" ], "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:PutObject", + "s3:DeleteObject", + "s3:ListBucket", + "s3:GetBucketLocation", + "s3:GetObjectVersion", + "s3:PutObjectAcl" + ], + "Resource": [ + "arn:aws:s3:::cn-seba-aws-sam-cli-managed-default-samclisourcebucket", + "arn:aws:s3:::cn-seba-aws-sam-cli-managed-default-samclisourcebucket/*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "s3:CreateBucket", + "s3:DeleteBucket", + "s3:ListAllMyBuckets" + ], + "Resource": "*" } ] } diff --git a/create_role.sh b/create_role.sh index 411052d..24e14ef 100644 --- a/create_role.sh +++ b/create_role.sh @@ -1094,12 +1094,36 @@ POLICY_DOCUMENT=$(cat < Date: Thu, 31 Jul 2025 18:37:08 +0900 Subject: [PATCH 20/21] fix: Add ProjectName parameter to template.yaml - Add ProjectName parameter to Parameters section - Fix PROJECT_NAME references to use ProjectName parameter - Update LayerName and Export Name to use ProjectName - This resolves CloudFormation template format error --- template.yaml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/template.yaml b/template.yaml index 6227a62..f668837 100644 --- a/template.yaml +++ b/template.yaml @@ -3,6 +3,10 @@ AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Parameters: + ProjectName: + Type: String + Default: LambdaFramework + Description: Project name for the Lambda layer Environment: Type: String Default: development @@ -15,8 +19,8 @@ Resources: LambdaFramework: Type: AWS::Serverless::LayerVersion Properties: - LayerName: !Sub "${PROJECT_NAME}-${Environment}" - Description: !Sub "Safe retry and stop framework - ${Environment}" + LayerName: !Sub "${ProjectName}" + Description: !Sub "Safe retry and stop framework" ContentUri: LambdaFramework RetentionPolicy: Retain CompatibleRuntimes: @@ -27,7 +31,4 @@ Outputs: LambdaFramework: Value: !Ref LambdaFramework Export: - Name: !Sub "Layer-${PROJECT_NAME}-${Environment}" - Environment: - Value: !Ref Environment - Description: Deployed environment + Name: !Sub "Layer-${ProjectName}" From 0aad2cbcbea5e9a4d0204e6638a6f2bea1260b6e Mon Sep 17 00:00:00 2001 From: Taikai Hirose Date: Thu, 31 Jul 2025 18:44:59 +0900 Subject: [PATCH 21/21] fix: Update GitHub Actions workflow for ProjectName parameter - Update parameter-overrides to use ProjectName instead of PROJECT_NAME - Ensure template.yaml parameter matches GitHub Actions workflow - Fix CloudFormation deployment parameter mapping --- .github/workflows/deploy.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5cfc445..d4d203f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -59,13 +59,12 @@ jobs: - name: Deploy with SAM run: | + STACK_NAME="LambdaFramework" # ブランチに基づいて環境設定を決定 if [ "${{ github.ref }}" = "refs/heads/main" ]; then - STACK_NAME="lambda-framework-prod" ENVIRONMENT="production" S3_BUCKET="${{ vars.S3_BUCKET_PROD }}" else - STACK_NAME="lambda-framework-dev" ENVIRONMENT="development" S3_BUCKET="${{ vars.S3_BUCKET_DEV }}" fi