diff --git a/.github/workflows/deploy-web-hosting.yml b/.github/workflows/deploy-web-hosting.yml index 95d7b33..924057a 100644 --- a/.github/workflows/deploy-web-hosting.yml +++ b/.github/workflows/deploy-web-hosting.yml @@ -4,6 +4,10 @@ name: Deploy to Web Hosting on: workflow_call: inputs: + environment: + description: "GitHub Environment name for secret access" + type: string + required: true deploy-type: description: "Deploy method ('ftp' or 'rsync')" type: string @@ -41,25 +45,6 @@ on: type: string required: false default: '' - secrets: - server-host: - required: true - server-user: - required: true - server-path: - required: true - server-password: - required: false - ssh-private-key: - required: false - slack-channel-id: - required: false - slack-bot-oauth-token: - required: false - slack-webhook-url: - required: false - slack-mention-user: - required: false permissions: {} @@ -68,6 +53,7 @@ jobs: name: Deploy to Web Hosting runs-on: ubuntu-24.04 timeout-minutes: 15 + environment: ${{ inputs.environment }} permissions: pull-requests: write @@ -83,9 +69,9 @@ jobs: - name: Check Slack configuration id: check-slack env: - SLACK_CHANNEL_ID: ${{ secrets.slack-channel-id }} - SLACK_BOT_OAUTH_TOKEN: ${{ secrets.slack-bot-oauth-token }} - SLACK_WEBHOOK_URL: ${{ secrets.slack-webhook-url }} + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + SLACK_BOT_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_OAUTH_TOKEN }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} run: | if [ -n "$SLACK_CHANNEL_ID" ] && [ -n "$SLACK_BOT_OAUTH_TOKEN" ]; then echo "success-enabled=true" >> "$GITHUB_OUTPUT" @@ -107,10 +93,10 @@ jobs: with: base-path: ${{ steps.compute-path.outputs.deploy-path }} output-dir: ${{ inputs.output-dir }} - ftp-server: ${{ secrets.server-host }} - ftp-username: ${{ secrets.server-user }} - ftp-password: ${{ secrets.server-password }} - ftp-path: ${{ secrets.server-path }}${{ steps.compute-path.outputs.deploy-path }} + ftp-server: ${{ secrets.SERVER_HOST }} + ftp-username: ${{ secrets.SERVER_USER }} + ftp-password: ${{ secrets.SERVER_PASSWORD }} + ftp-path: ${{ secrets.SERVER_PATH }}${{ steps.compute-path.outputs.deploy-path }} dry-run: ${{ inputs.dry-run }} is-production: ${{ steps.compute-path.outputs.is-production }} @@ -121,10 +107,10 @@ jobs: with: base-path: ${{ steps.compute-path.outputs.deploy-path }} output-dir: ${{ inputs.output-dir }} - ssh-host: ${{ secrets.server-host }} - ssh-user: ${{ secrets.server-user }} - ssh-private-key: ${{ secrets.ssh-private-key }} - ssh-path: ${{ secrets.server-path }}${{ steps.compute-path.outputs.deploy-path }} + ssh-host: ${{ secrets.SERVER_HOST }} + ssh-user: ${{ secrets.SERVER_USER }} + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + ssh-path: ${{ secrets.SERVER_PATH }}${{ steps.compute-path.outputs.deploy-path }} dry-run: ${{ inputs.dry-run }} is-production: ${{ steps.compute-path.outputs.is-production }} @@ -162,8 +148,8 @@ jobs: if: ${{ success() && github.event_name != 'pull_request' && steps.check-slack.outputs.success-enabled == 'true' }} uses: kryota-dev/actions/.github/actions/slack-notify-success@568519d2e5e2722d8d2340f594f6af3e1564852e # v0.0.7 with: - channel-id: ${{ secrets.slack-channel-id }} - bot-oauth-token: ${{ secrets.slack-bot-oauth-token }} + channel-id: ${{ secrets.SLACK_CHANNEL_ID }} + bot-oauth-token: ${{ secrets.SLACK_BOT_OAUTH_TOKEN }} title: 'Web Hosting deploy succeeded' message: '${{ inputs.home-url }}${{ steps.compute-path.outputs.deploy-path }}/' @@ -171,8 +157,8 @@ jobs: if: ${{ failure() && github.event_name != 'pull_request' && steps.check-slack.outputs.failure-enabled == 'true' }} uses: kryota-dev/actions/.github/actions/slack-notify-failure@568519d2e5e2722d8d2340f594f6af3e1564852e # v0.0.7 with: - webhook-url: ${{ secrets.slack-webhook-url }} - mention-user: ${{ secrets.slack-mention-user }} + webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} + mention-user: ${{ secrets.SLACK_MENTION_USER }} title: 'Web Hosting deploy failed' # --- Hide Previous Failed Comments --- diff --git a/.github/workflows/docs/deploy-web-hosting.ja.md b/.github/workflows/docs/deploy-web-hosting.ja.md index d0da7e1..d6c20c9 100644 --- a/.github/workflows/docs/deploy-web-hosting.ja.md +++ b/.github/workflows/docs/deploy-web-hosting.ja.md @@ -15,6 +15,10 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0 with: + # environment - シークレットアクセス用の GitHub Environment 名 + # Required + environment: 'production' + # deploy-type - デプロイ方法('ftp' または 'rsync') # Required deploy-type: 'ftp' @@ -46,48 +50,13 @@ jobs: # ref-name - ブランチ名の上書き(空の場合は github context から自動取得) # Optional (default: '') ref-name: '' - secrets: - # server-host - デプロイ先サーバーのホスト名 - # Required - server-host: ${{ secrets.SERVER_HOST }} - - # server-user - デプロイ先サーバーのユーザー名 - # Required - server-user: ${{ secrets.SERVER_USER }} - - # server-path - デプロイ先サーバーのパス - # Required - server-path: ${{ secrets.SERVER_PATH }} - - # server-password - デプロイ先サーバーのパスワード(FTP 使用時に必要) - # Optional - server-password: ${{ secrets.SERVER_PASSWORD }} - - # ssh-private-key - SSH 秘密鍵(rsync 使用時に必要) - # Optional - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - - # slack-channel-id - Slack 通知先チャンネル ID - # Optional - slack-channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - - # slack-bot-oauth-token - Slack Bot の OAuth トークン - # Optional - slack-bot-oauth-token: ${{ secrets.SLACK_BOT_OAUTH_TOKEN }} - - # slack-webhook-url - Slack Incoming Webhook URL - # Optional - slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} - - # slack-mention-user - Slack で失敗時にメンションするユーザー - # Optional - slack-mention-user: ${{ secrets.SLACK_MENTION_USER }} ``` ## Inputs | Name | Description | Required | Default | |------|-------------|----------|---------| +| `environment` | シークレットアクセス用の GitHub Environment 名 | Yes | - | | `deploy-type` | デプロイ方法(`'ftp'` または `'rsync'`) | Yes | - | | `artifact-name` | ダウンロードするビルドアーティファクトの名前 | Yes | - | | `output-dir` | ビルド出力ディレクトリ名 | Yes | - | @@ -97,19 +66,21 @@ jobs: | `production-branch` | 本番ブランチ名 | No | `'main'` | | `ref-name` | ブランチ名の上書き(空の場合は github context から自動取得) | No | `''` | -## Secrets +## Environment Secrets + +`environment` input で指定した GitHub Environment に以下のシークレットを設定する必要があります: | Name | Description | Required | |------|-------------|----------| -| `server-host` | デプロイ先サーバーのホスト名 | Yes | -| `server-user` | デプロイ先サーバーのユーザー名 | Yes | -| `server-path` | デプロイ先サーバーのパス | Yes | -| `server-password` | デプロイ先サーバーのパスワード(FTP 使用時に必要) | No | -| `ssh-private-key` | SSH 秘密鍵(rsync 使用時に必要) | No | -| `slack-channel-id` | Slack 通知先チャンネル ID | No | -| `slack-bot-oauth-token` | Slack Bot の OAuth トークン | No | -| `slack-webhook-url` | Slack Incoming Webhook URL | No | -| `slack-mention-user` | Slack で失敗時にメンションするユーザー | No | +| `SERVER_HOST` | デプロイ先サーバーのホスト名 | Yes | +| `SERVER_USER` | デプロイ先サーバーのユーザー名 | Yes | +| `SERVER_PATH` | デプロイ先サーバーのパス | Yes | +| `SERVER_PASSWORD` | デプロイ先サーバーのパスワード(FTP 使用時に必要) | Conditional | +| `SSH_PRIVATE_KEY` | SSH 秘密鍵(rsync 使用時に必要) | Conditional | +| `SLACK_CHANNEL_ID` | Slack 通知先チャンネル ID | No | +| `SLACK_BOT_OAUTH_TOKEN` | Slack Bot の OAuth トークン | No | +| `SLACK_WEBHOOK_URL` | Slack Incoming Webhook URL | No | +| `SLACK_MENTION_USER` | Slack で失敗時にメンションするユーザー | No | ## Permissions @@ -128,14 +99,10 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0 with: + environment: 'production' deploy-type: 'ftp' artifact-name: 'build-output' output-dir: 'dist' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - server-password: ${{ secrets.SERVER_PASSWORD }} ``` ### rsync でデプロイする(Slack 通知付き) @@ -147,20 +114,12 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0 with: + environment: 'production' deploy-type: 'rsync' artifact-name: 'build-output' output-dir: 'dist' base-path-prefix: '/my-project' home-url: 'https://example.com' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - slack-channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - slack-bot-oauth-token: ${{ secrets.SLACK_BOT_OAUTH_TOKEN }} - slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} - slack-mention-user: ${{ secrets.SLACK_MENTION_USER }} ``` ### ドライランで確認する @@ -172,15 +131,11 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0 with: + environment: 'staging' deploy-type: 'rsync' artifact-name: 'build-output' output-dir: 'dist' dry-run: 'true' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ``` ## Behavior @@ -188,7 +143,7 @@ jobs: このワークフローは `deploy` ジョブで構成され、以下の順序で実行されます。 1. `compute-web-hosting-deploy-path` Composite Action でデプロイ先パスを計算 -2. Slack 設定チェック(`slack-channel-id` + `slack-bot-oauth-token` があれば成功通知可能、`slack-webhook-url` があれば失敗通知可能) +2. Slack 設定チェック(`SLACK_CHANNEL_ID` + `SLACK_BOT_OAUTH_TOKEN` があれば成功通知可能、`SLACK_WEBHOOK_URL` があれば失敗通知可能) 3. `actions/download-artifact@v4.3.0` でビルドアーティファクトをダウンロード 4. `deploy-type` の値に応じてデプロイを実行 - `'ftp'`: `deploy-web-hosting-ftp` Composite Action を使用 @@ -199,6 +154,7 @@ jobs: ## Prerequisites +- 呼び出し元リポジトリに `environment` input に対応する GitHub Environment が存在し、必要なシークレットが Environment レベルで設定されていること - 呼び出し元ワークフローで `actions/upload-artifact` によるビルド成果物のアップロードが完了していること -- `deploy-type` が `'ftp'` の場合: `server-password` が必要 -- `deploy-type` が `'rsync'` の場合: `ssh-private-key` が必要 +- `deploy-type` が `'ftp'` の場合: `SERVER_PASSWORD` が必要 +- `deploy-type` が `'rsync'` の場合: `SSH_PRIVATE_KEY` が必要 diff --git a/.github/workflows/docs/deploy-web-hosting.md b/.github/workflows/docs/deploy-web-hosting.md index 39103de..6b19575 100644 --- a/.github/workflows/docs/deploy-web-hosting.md +++ b/.github/workflows/docs/deploy-web-hosting.md @@ -15,6 +15,10 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0 with: + # environment - GitHub Environment name for secret access + # Required + environment: 'production' + # deploy-type - Deployment method ('ftp' or 'rsync') # Required deploy-type: 'ftp' @@ -46,48 +50,13 @@ jobs: # ref-name - Branch name override (auto-detected from github context if empty) # Optional (default: '') ref-name: '' - secrets: - # server-host - Deployment server hostname - # Required - server-host: ${{ secrets.SERVER_HOST }} - - # server-user - Deployment server username - # Required - server-user: ${{ secrets.SERVER_USER }} - - # server-path - Deployment server path - # Required - server-path: ${{ secrets.SERVER_PATH }} - - # server-password - Deployment server password (required for FTP) - # Optional - server-password: ${{ secrets.SERVER_PASSWORD }} - - # ssh-private-key - SSH private key (required for rsync) - # Optional - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - - # slack-channel-id - Slack notification channel ID - # Optional - slack-channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - - # slack-bot-oauth-token - Slack Bot OAuth token - # Optional - slack-bot-oauth-token: ${{ secrets.SLACK_BOT_OAUTH_TOKEN }} - - # slack-webhook-url - Slack Incoming Webhook URL - # Optional - slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} - - # slack-mention-user - Slack user to mention on failure - # Optional - slack-mention-user: ${{ secrets.SLACK_MENTION_USER }} ``` ## Inputs | Name | Description | Required | Default | |------|-------------|----------|---------| +| `environment` | GitHub Environment name for secret access | Yes | - | | `deploy-type` | Deployment method (`'ftp'` or `'rsync'`) | Yes | - | | `artifact-name` | Name of the build artifact to download | Yes | - | | `output-dir` | Build output directory name | Yes | - | @@ -97,19 +66,21 @@ jobs: | `production-branch` | Production branch name | No | `'main'` | | `ref-name` | Branch name override (auto-detected from github context if empty) | No | `''` | -## Secrets +## Environment Secrets + +The following secrets must be configured in the GitHub Environment specified by the `environment` input: | Name | Description | Required | |------|-------------|----------| -| `server-host` | Deployment server hostname | Yes | -| `server-user` | Deployment server username | Yes | -| `server-path` | Deployment server path | Yes | -| `server-password` | Deployment server password (required for FTP) | No | -| `ssh-private-key` | SSH private key (required for rsync) | No | -| `slack-channel-id` | Slack notification channel ID | No | -| `slack-bot-oauth-token` | Slack Bot OAuth token | No | -| `slack-webhook-url` | Slack Incoming Webhook URL | No | -| `slack-mention-user` | Slack user to mention on failure | No | +| `SERVER_HOST` | Deployment server hostname | Yes | +| `SERVER_USER` | Deployment server username | Yes | +| `SERVER_PATH` | Deployment server path | Yes | +| `SERVER_PASSWORD` | Deployment server password (required for FTP) | Conditional | +| `SSH_PRIVATE_KEY` | SSH private key (required for rsync) | Conditional | +| `SLACK_CHANNEL_ID` | Slack notification channel ID | No | +| `SLACK_BOT_OAUTH_TOKEN` | Slack Bot OAuth token | No | +| `SLACK_WEBHOOK_URL` | Slack Incoming Webhook URL | No | +| `SLACK_MENTION_USER` | Slack user to mention on failure | No | ## Permissions @@ -128,14 +99,10 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0 with: + environment: 'production' deploy-type: 'ftp' artifact-name: 'build-output' output-dir: 'dist' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - server-password: ${{ secrets.SERVER_PASSWORD }} ``` ### Deploy via rsync (with Slack notifications) @@ -147,20 +114,12 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0 with: + environment: 'production' deploy-type: 'rsync' artifact-name: 'build-output' output-dir: 'dist' base-path-prefix: '/my-project' home-url: 'https://example.com' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - slack-channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - slack-bot-oauth-token: ${{ secrets.SLACK_BOT_OAUTH_TOKEN }} - slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} - slack-mention-user: ${{ secrets.SLACK_MENTION_USER }} ``` ### Verify with dry-run @@ -172,15 +131,11 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0 with: + environment: 'staging' deploy-type: 'rsync' artifact-name: 'build-output' output-dir: 'dist' dry-run: 'true' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ``` ## Behavior @@ -188,7 +143,7 @@ jobs: This workflow consists of a `deploy` job and executes in the following order: 1. Compute the deployment path using the `compute-web-hosting-deploy-path` Composite Action -2. Check Slack configuration (`slack-channel-id` + `slack-bot-oauth-token` enables success notifications, `slack-webhook-url` enables failure notifications) +2. Check Slack configuration (`SLACK_CHANNEL_ID` + `SLACK_BOT_OAUTH_TOKEN` enables success notifications, `SLACK_WEBHOOK_URL` enables failure notifications) 3. Download build artifacts with `actions/download-artifact@v4.3.0` 4. Execute deployment based on the `deploy-type` value - `'ftp'`: Uses the `deploy-web-hosting-ftp` Composite Action @@ -199,6 +154,7 @@ This workflow consists of a `deploy` job and executes in the following order: ## Prerequisites +- A GitHub Environment matching the `environment` input must exist in the caller's repository, with the required secrets configured at the environment level - Build artifacts must have been uploaded via `actions/upload-artifact` in the calling workflow -- For `deploy-type` `'ftp'`: `server-password` is required -- For `deploy-type` `'rsync'`: `ssh-private-key` is required +- For `deploy-type` `'ftp'`: `SERVER_PASSWORD` is required +- For `deploy-type` `'rsync'`: `SSH_PRIVATE_KEY` is required diff --git a/.github/workflows/docs/tagpr-release.ja.md b/.github/workflows/docs/tagpr-release.ja.md index 8b76d89..d4cb7e5 100644 --- a/.github/workflows/docs/tagpr-release.ja.md +++ b/.github/workflows/docs/tagpr-release.ja.md @@ -15,21 +15,25 @@ jobs: contents: write pull-requests: write uses: kryota-dev/actions/.github/workflows/tagpr-release.yml@v0 - secrets: - # app-token - tagpr 用の Personal Access Token('repo' と 'workflow' スコープが必要) + with: + # environment - シークレットアクセス用の GitHub Environment 名 # Required - app-token: ${{ secrets.APP_TOKEN }} + environment: 'release' ``` ## Inputs -None +| Name | Description | Required | Default | +|------|-------------|----------|---------| +| `environment` | シークレットアクセス用の GitHub Environment 名 | Yes | - | -## Secrets +## Environment Secrets + +`environment` input で指定した GitHub Environment に以下のシークレットを設定する必要があります: | Name | Description | Required | |------|-------------|----------| -| `app-token` | tagpr 用の Personal Access Token(`repo` と `workflow` スコープが必要) | Yes | +| `APP_TOKEN` | tagpr 用の Personal Access Token(`repo` と `workflow` スコープが必要) | Yes | ## Outputs @@ -55,8 +59,8 @@ jobs: contents: write pull-requests: write uses: kryota-dev/actions/.github/workflows/tagpr-release.yml@v0 - secrets: - app-token: ${{ secrets.APP_TOKEN }} + with: + environment: 'release' ``` ### リリース後に後続ジョブを実行する @@ -68,8 +72,8 @@ jobs: contents: write pull-requests: write uses: kryota-dev/actions/.github/workflows/tagpr-release.yml@v0 - secrets: - app-token: ${{ secrets.APP_TOKEN }} + with: + environment: 'release' post-release: needs: release @@ -87,19 +91,20 @@ jobs: ### tagpr ジョブ -1. `actions/checkout@v6` でリポジトリをチェックアウト(token: `app-token`、`persist-credentials: false`) -2. `Songmu/tagpr@v1.17.1` を実行してリリース PR の作成・マージ・タグ付けを行う(`GITHUB_TOKEN: app-token`) +1. `actions/checkout@v6` でリポジトリをチェックアウト(token: `APP_TOKEN`、`persist-credentials: false`) +2. `Songmu/tagpr@v1.17.1` を実行してリリース PR の作成・マージ・タグ付けを行う(`GITHUB_TOKEN: APP_TOKEN`) 3. リリースされた場合はバージョンタグを `tag` output として出力(リリースがなければ空) ### bump_major_tag ジョブ `tagpr` ジョブの完了後、タグが作成された場合(`tag != ''`)のみ実行されます。 -1. `actions/checkout@v6` でリポジトリをチェックアウト(token: `app-token`、`persist-credentials: false`) +1. `actions/checkout@v6` でリポジトリをチェックアウト(token: `APP_TOKEN`、`persist-credentials: false`) 2. タグからメジャーバージョンを抽出(例: `v1.2.3` → `v1`) 3. `git tag -f` でメジャータグを更新し、`git push --force` でリモートに反映 ## Prerequisites +- 呼び出し元リポジトリに `environment` input に対応する GitHub Environment が存在し、`APP_TOKEN` シークレットが Environment レベルで設定されていること - GitHub App Token または Personal Access Token(`repo` + `workflow` スコープ)が必要 - `.tagpr` 設定ファイルがリポジトリに存在すること diff --git a/.github/workflows/docs/tagpr-release.md b/.github/workflows/docs/tagpr-release.md index 377fcac..2719e66 100644 --- a/.github/workflows/docs/tagpr-release.md +++ b/.github/workflows/docs/tagpr-release.md @@ -15,21 +15,25 @@ jobs: contents: write pull-requests: write uses: kryota-dev/actions/.github/workflows/tagpr-release.yml@v0 - secrets: - # app-token - Personal Access Token for tagpr (requires 'repo' and 'workflow' scopes) + with: + # environment - GitHub Environment name for secret access # Required - app-token: ${{ secrets.APP_TOKEN }} + environment: 'release' ``` ## Inputs -None +| Name | Description | Required | Default | +|------|-------------|----------|---------| +| `environment` | GitHub Environment name for secret access | Yes | - | -## Secrets +## Environment Secrets + +The following secrets must be configured in the GitHub Environment specified by the `environment` input: | Name | Description | Required | |------|-------------|----------| -| `app-token` | Personal Access Token for tagpr (requires `repo` and `workflow` scopes) | Yes | +| `APP_TOKEN` | Personal Access Token for tagpr (requires `repo` and `workflow` scopes) | Yes | ## Outputs @@ -55,8 +59,8 @@ jobs: contents: write pull-requests: write uses: kryota-dev/actions/.github/workflows/tagpr-release.yml@v0 - secrets: - app-token: ${{ secrets.APP_TOKEN }} + with: + environment: 'release' ``` ### Running follow-up jobs after release @@ -68,8 +72,8 @@ jobs: contents: write pull-requests: write uses: kryota-dev/actions/.github/workflows/tagpr-release.yml@v0 - secrets: - app-token: ${{ secrets.APP_TOKEN }} + with: + environment: 'release' post-release: needs: release @@ -87,19 +91,20 @@ This workflow consists of two jobs: `tagpr` and `bump_major_tag`. ### tagpr Job -1. Check out the repository with `actions/checkout@v6` (token: `app-token`, `persist-credentials: false`) -2. Run `Songmu/tagpr@v1.17.1` to create/merge release PRs and tag releases (`GITHUB_TOKEN: app-token`) +1. Check out the repository with `actions/checkout@v6` (token: `APP_TOKEN`, `persist-credentials: false`) +2. Run `Songmu/tagpr@v1.17.1` to create/merge release PRs and tag releases (`GITHUB_TOKEN: APP_TOKEN`) 3. If a release is made, output the version tag as the `tag` output (empty if no release) ### bump_major_tag Job Runs only after the `tagpr` job completes and a tag was created (`tag != ''`). -1. Check out the repository with `actions/checkout@v6` (token: `app-token`, `persist-credentials: false`) +1. Check out the repository with `actions/checkout@v6` (token: `APP_TOKEN`, `persist-credentials: false`) 2. Extract the major version from the tag (e.g., `v1.2.3` → `v1`) 3. Update the major tag with `git tag -f` and push to remote with `git push --force` ## Prerequisites +- A GitHub Environment matching the `environment` input must exist in the caller's repository, with `APP_TOKEN` configured as an environment secret - GitHub App Token or Personal Access Token (requires `repo` + `workflow` scopes) - `.tagpr` configuration file must exist in the repository diff --git a/.github/workflows/docs/undeploy-web-hosting.ja.md b/.github/workflows/docs/undeploy-web-hosting.ja.md index 7893c5f..f942b36 100644 --- a/.github/workflows/docs/undeploy-web-hosting.ja.md +++ b/.github/workflows/docs/undeploy-web-hosting.ja.md @@ -16,6 +16,10 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/undeploy-web-hosting.yml@v0 with: + # environment - シークレットアクセス用の GitHub Environment 名 + # Required + environment: 'production' + # deploy-type - デプロイ方法('ftp' または 'rsync') # Required deploy-type: 'ftp' @@ -35,47 +39,30 @@ jobs: # dry-run - ドライランモード # Optional (default: 'false') dry-run: 'false' - secrets: - # server-host - デプロイ先サーバーのホスト名 - # Required - server-host: ${{ secrets.SERVER_HOST }} - - # server-user - デプロイ先サーバーのユーザー名 - # Required - server-user: ${{ secrets.SERVER_USER }} - - # server-path - デプロイ先サーバーのパス - # Required - server-path: ${{ secrets.SERVER_PATH }} - - # server-password - デプロイ先サーバーのパスワード(FTP 使用時に必要) - # Optional - server-password: ${{ secrets.SERVER_PASSWORD }} - - # ssh-private-key - SSH 秘密鍵(rsync 使用時に必要) - # Optional - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ``` ## Inputs | Name | Description | Required | Default | |------|-------------|----------|---------| +| `environment` | シークレットアクセス用の GitHub Environment 名 | Yes | - | | `deploy-type` | デプロイ方法(`'ftp'` または `'rsync'`) | Yes | - | | `base-path-prefix` | プロジェクト固有のパスプレフィックス(例: `'/'`) | No | `''` | | `production-branch` | 本番ブランチ名 | No | `'main'` | | `ref-name` | ブランチ名の上書き(空の場合は github context から自動取得) | No | `''` | | `dry-run` | ドライランモード | No | `'false'` | -## Secrets +## Environment Secrets + +`environment` input で指定した GitHub Environment に以下のシークレットを設定する必要があります: | Name | Description | Required | |------|-------------|----------| -| `server-host` | デプロイ先サーバーのホスト名 | Yes | -| `server-user` | デプロイ先サーバーのユーザー名 | Yes | -| `server-path` | デプロイ先サーバーのパス | Yes | -| `server-password` | デプロイ先サーバーのパスワード(FTP 使用時に必要) | No | -| `ssh-private-key` | SSH 秘密鍵(rsync 使用時に必要) | No | +| `SERVER_HOST` | デプロイ先サーバーのホスト名 | Yes | +| `SERVER_USER` | デプロイ先サーバーのユーザー名 | Yes | +| `SERVER_PATH` | デプロイ先サーバーのパス | Yes | +| `SERVER_PASSWORD` | デプロイ先サーバーのパスワード(FTP 使用時に必要) | Conditional | +| `SSH_PRIVATE_KEY` | SSH 秘密鍵(rsync 使用時に必要) | Conditional | ## Permissions @@ -96,12 +83,8 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/undeploy-web-hosting.yml@v0 with: + environment: 'production' deploy-type: 'ftp' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - server-password: ${{ secrets.SERVER_PASSWORD }} ``` ### rsync でフィーチャー環境を削除する(パスプレフィックス付き) @@ -114,13 +97,9 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/undeploy-web-hosting.yml@v0 with: + environment: 'production' deploy-type: 'rsync' base-path-prefix: '/my-project' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ``` ### ドライランで確認する @@ -133,13 +112,9 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/undeploy-web-hosting.yml@v0 with: + environment: 'staging' deploy-type: 'rsync' dry-run: 'true' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ``` ## Behavior @@ -155,5 +130,6 @@ jobs: ## Prerequisites -- `deploy-type` が `'ftp'` の場合: `server-password` が必要 -- `deploy-type` が `'rsync'` の場合: `ssh-private-key` が必要 +- 呼び出し元リポジトリに `environment` input に対応する GitHub Environment が存在し、必要なシークレットが Environment レベルで設定されていること +- `deploy-type` が `'ftp'` の場合: `SERVER_PASSWORD` が必要 +- `deploy-type` が `'rsync'` の場合: `SSH_PRIVATE_KEY` が必要 diff --git a/.github/workflows/docs/undeploy-web-hosting.md b/.github/workflows/docs/undeploy-web-hosting.md index 23a071e..31b9607 100644 --- a/.github/workflows/docs/undeploy-web-hosting.md +++ b/.github/workflows/docs/undeploy-web-hosting.md @@ -16,6 +16,10 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/undeploy-web-hosting.yml@v0 with: + # environment - GitHub Environment name for secret access + # Required + environment: 'production' + # deploy-type - Deployment method ('ftp' or 'rsync') # Required deploy-type: 'ftp' @@ -35,47 +39,30 @@ jobs: # dry-run - Dry-run mode # Optional (default: 'false') dry-run: 'false' - secrets: - # server-host - Deployment server hostname - # Required - server-host: ${{ secrets.SERVER_HOST }} - - # server-user - Deployment server username - # Required - server-user: ${{ secrets.SERVER_USER }} - - # server-path - Deployment server path - # Required - server-path: ${{ secrets.SERVER_PATH }} - - # server-password - Deployment server password (required for FTP) - # Optional - server-password: ${{ secrets.SERVER_PASSWORD }} - - # ssh-private-key - SSH private key (required for rsync) - # Optional - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ``` ## Inputs | Name | Description | Required | Default | |------|-------------|----------|---------| +| `environment` | GitHub Environment name for secret access | Yes | - | | `deploy-type` | Deployment method (`'ftp'` or `'rsync'`) | Yes | - | | `base-path-prefix` | Project-specific path prefix (e.g., `'/'`) | No | `''` | | `production-branch` | Production branch name | No | `'main'` | | `ref-name` | Branch name override (auto-detected from github context if empty) | No | `''` | | `dry-run` | Dry-run mode | No | `'false'` | -## Secrets +## Environment Secrets + +The following secrets must be configured in the GitHub Environment specified by the `environment` input: | Name | Description | Required | |------|-------------|----------| -| `server-host` | Deployment server hostname | Yes | -| `server-user` | Deployment server username | Yes | -| `server-path` | Deployment server path | Yes | -| `server-password` | Deployment server password (required for FTP) | No | -| `ssh-private-key` | SSH private key (required for rsync) | No | +| `SERVER_HOST` | Deployment server hostname | Yes | +| `SERVER_USER` | Deployment server username | Yes | +| `SERVER_PATH` | Deployment server path | Yes | +| `SERVER_PASSWORD` | Deployment server password (required for FTP) | Conditional | +| `SSH_PRIVATE_KEY` | SSH private key (required for rsync) | Conditional | ## Permissions @@ -96,12 +83,8 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/undeploy-web-hosting.yml@v0 with: + environment: 'production' deploy-type: 'ftp' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - server-password: ${{ secrets.SERVER_PASSWORD }} ``` ### Remove feature environment via rsync (with path prefix) @@ -114,13 +97,9 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/undeploy-web-hosting.yml@v0 with: + environment: 'production' deploy-type: 'rsync' base-path-prefix: '/my-project' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ``` ### Verify with dry-run @@ -133,13 +112,9 @@ jobs: pull-requests: write uses: kryota-dev/actions/.github/workflows/undeploy-web-hosting.yml@v0 with: + environment: 'staging' deploy-type: 'rsync' dry-run: 'true' - secrets: - server-host: ${{ secrets.SERVER_HOST }} - server-user: ${{ secrets.SERVER_USER }} - server-path: ${{ secrets.SERVER_PATH }} - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ``` ## Behavior @@ -155,5 +130,6 @@ This workflow consists of a `delete` job and executes in the following order: ## Prerequisites -- For `deploy-type` `'ftp'`: `server-password` is required -- For `deploy-type` `'rsync'`: `ssh-private-key` is required +- A GitHub Environment matching the `environment` input must exist in the caller's repository, with the required secrets configured at the environment level +- For `deploy-type` `'ftp'`: `SERVER_PASSWORD` is required +- For `deploy-type` `'rsync'`: `SSH_PRIVATE_KEY` is required diff --git a/.github/workflows/my-release.yml b/.github/workflows/my-release.yml index bb1a0d5..89e0764 100644 --- a/.github/workflows/my-release.yml +++ b/.github/workflows/my-release.yml @@ -15,5 +15,5 @@ jobs: contents: write pull-requests: write uses: ./.github/workflows/tagpr-release.yml - secrets: - app-token: ${{ secrets.APP_TOKEN }} + with: + environment: release diff --git a/.github/workflows/my-update-release-pr.yml b/.github/workflows/my-update-release-pr.yml index 9a32fe9..211d476 100644 --- a/.github/workflows/my-update-release-pr.yml +++ b/.github/workflows/my-update-release-pr.yml @@ -18,5 +18,5 @@ jobs: contents: write pull-requests: write uses: ./.github/workflows/tagpr-release.yml - secrets: - app-token: ${{ secrets.APP_TOKEN }} + with: + environment: release diff --git a/.github/workflows/tagpr-release.yml b/.github/workflows/tagpr-release.yml index 0d38633..1555c3c 100644 --- a/.github/workflows/tagpr-release.yml +++ b/.github/workflows/tagpr-release.yml @@ -3,9 +3,10 @@ name: tagpr Release on: workflow_call: - secrets: - app-token: - description: "Personal Access Token for tagpr (requires 'repo' and 'workflow' scopes)" + inputs: + environment: + description: "GitHub Environment name for secret access" + type: string required: true outputs: tag: @@ -22,6 +23,7 @@ jobs: tagpr: runs-on: ubuntu-latest timeout-minutes: 10 + environment: ${{ inputs.environment }} permissions: contents: write pull-requests: write @@ -30,31 +32,32 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: - token: ${{ secrets.app-token }} + token: ${{ secrets.APP_TOKEN }} persist-credentials: false - uses: Songmu/tagpr@b3fb89424646b06c8aa460f50307c60b6a541425 # v1.17.1 id: tagpr env: - GITHUB_TOKEN: ${{ secrets.app-token }} + GITHUB_TOKEN: ${{ secrets.APP_TOKEN }} bump_major_tag: needs: tagpr if: needs.tagpr.outputs.tag != '' runs-on: ubuntu-latest timeout-minutes: 5 + environment: ${{ inputs.environment }} permissions: contents: write steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: - token: ${{ secrets.app-token }} + token: ${{ secrets.APP_TOKEN }} persist-credentials: false - name: Update major tag env: TAG: ${{ needs.tagpr.outputs.tag }} - GITHUB_TOKEN: ${{ secrets.app-token }} + GITHUB_TOKEN: ${{ secrets.APP_TOKEN }} REPO: ${{ github.repository }} run: | git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${REPO}.git" diff --git a/.github/workflows/undeploy-web-hosting.yml b/.github/workflows/undeploy-web-hosting.yml index ad6bdc4..93877e2 100644 --- a/.github/workflows/undeploy-web-hosting.yml +++ b/.github/workflows/undeploy-web-hosting.yml @@ -4,6 +4,10 @@ name: Undeploy from Web Hosting on: workflow_call: inputs: + environment: + description: "GitHub Environment name for secret access" + type: string + required: true deploy-type: description: "Deploy method ('ftp' or 'rsync')" type: string @@ -28,17 +32,6 @@ on: type: string required: false default: 'false' - secrets: - server-host: - required: true - server-user: - required: true - server-path: - required: true - server-password: - required: false - ssh-private-key: - required: false permissions: {} @@ -47,6 +40,7 @@ jobs: name: Undeploy from Web Hosting runs-on: ubuntu-24.04 timeout-minutes: 10 + environment: ${{ inputs.environment }} permissions: contents: read pull-requests: write @@ -65,10 +59,10 @@ jobs: if: ${{ inputs.deploy-type == 'ftp' }} uses: kryota-dev/actions/.github/actions/undeploy-web-hosting-ftp@568519d2e5e2722d8d2340f594f6af3e1564852e # v0.0.7 with: - ftp-server: ${{ secrets.server-host }} - ftp-username: ${{ secrets.server-user }} - ftp-password: ${{ secrets.server-password }} - target-path: ${{ secrets.server-path }}${{ steps.compute-path.outputs.deploy-path }} + ftp-server: ${{ secrets.SERVER_HOST }} + ftp-username: ${{ secrets.SERVER_USER }} + ftp-password: ${{ secrets.SERVER_PASSWORD }} + target-path: ${{ secrets.SERVER_PATH }}${{ steps.compute-path.outputs.deploy-path }} dry-run: ${{ inputs.dry-run }} # --- rsync Delete --- @@ -76,10 +70,10 @@ jobs: if: ${{ inputs.deploy-type == 'rsync' }} uses: kryota-dev/actions/.github/actions/undeploy-web-hosting-rsync@568519d2e5e2722d8d2340f594f6af3e1564852e # v0.0.7 with: - ssh-host: ${{ secrets.server-host }} - ssh-user: ${{ secrets.server-user }} - ssh-private-key: ${{ secrets.ssh-private-key }} - target-path: ${{ secrets.server-path }}${{ steps.compute-path.outputs.deploy-path }} + ssh-host: ${{ secrets.SERVER_HOST }} + ssh-user: ${{ secrets.SERVER_USER }} + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + target-path: ${{ secrets.SERVER_PATH }}${{ steps.compute-path.outputs.deploy-path }} dry-run: ${{ inputs.dry-run }} # --- PR Comments --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 56259ce..cac54ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [Unreleased] +### Breaking Changes +- Add required `environment` input to `deploy-web-hosting.yml`, `tagpr-release.yml`, and `undeploy-web-hosting.yml` to enforce GitHub Environment-scoped secret access (zizmor `secrets-outside-env` audit). Existing callers must create a GitHub Environment and pass the `environment` input. +- Remove `workflow_call.secrets` from all Reusable Workflows. Secrets are now read directly from the GitHub Environment via `environment:` on each job. Callers no longer pass `secrets:` blocks; instead, configure secrets at the environment level (UPPER_SNAKE_CASE naming: `APP_TOKEN`, `SERVER_HOST`, etc.). + ## [v0.1.0](https://github.com/kryota-dev/actions/compare/v0.0.9...v0.1.0) - 2026-03-06 ### Other Changes - docs(copilot): add custom instructions for Copilot agents by @kryota-dev in https://github.com/kryota-dev/actions/pull/46