Skip to content

release

release #31

Workflow file for this run

name: release
# d-party モノレポ root の release ワークフローから統一バージョンを受け取って起動される。
# 旧 bump_type 方式は廃止し、version を外部入力で受け取る。
# build + Chrome Web Store への公開は従来どおりここで行う。
on:
workflow_dispatch:
inputs:
version:
description: "Release version (X.Y.Z)"
required: true
type: string
release_note:
description: "Release notes (optional)"
required: false
type: string
publish:
description: "Publish to Chrome Web Store (false = upload only; publish manually in the dashboard)"
required: false
type: boolean
default: false
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: main
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Set version
id: version
env:
VERSION_NUM: ${{ inputs.version }}
run: |
echo "new_version=v${VERSION_NUM}" >> "$GITHUB_OUTPUT"
echo "version_num=${VERSION_NUM}" >> "$GITHUB_OUTPUT"
node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.version=process.env.VERSION_NUM;fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n');"
node -e "const fs=require('fs');const m=JSON.parse(fs.readFileSync('public/manifest.json','utf8'));m.version=process.env.VERSION_NUM;fs.writeFileSync('public/manifest.json',JSON.stringify(m,null,2)+'\n');"
- name: Commit and push version bump
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add package.json public/manifest.json
if git diff --cached --quiet; then
echo "version files already at ${{ steps.version.outputs.new_version }}; skipping bump commit"
else
git commit -m "chore: bump version to ${{ steps.version.outputs.new_version }} [skip ci]"
git push origin HEAD:main
fi
- name: Force-update release tag
run: |
set -euo pipefail
git tag -f "${{ steps.version.outputs.new_version }}"
git push origin "refs/tags/${{ steps.version.outputs.new_version }}" --force
- name: Generate API client
run: pnpm api:generate
- name: Build extension
run: pnpm build:prod
- name: Package extension
run: |
cd dist
zip -r "../d-party_${{ steps.version.outputs.new_version }}.zip" .
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.new_version }}
name: Release ${{ steps.version.outputs.new_version }}
body: ${{ inputs.release_note }}
files: d-party_${{ steps.version.outputs.new_version }}.zip
generate_release_notes: true
target_commitish: main
# Chrome Web Store API を curl で直接叩く。
# 以前は mnao305/chrome-extension-upload を使っていたが、API のレスポンスボディを
# 一切ログに出さない仕様のため 400 等の障害切り分けが不可能だった
# (`itemError[].error_code` / `uploadState` / `statusDetail` が見えない)。
# ここでは OAuth2 token exchange → upload(PUT) → publish(POST) を順に実行し、
# 各レスポンスを JSON のまま GitHub Actions ログへ出力する。
# 参考: https://developer.chrome.com/docs/webstore/using-api
- name: Upload to Chrome Web Store
env:
EXTENSION_ID: ${{ secrets.EXTENSION_ID }}
CLIENT_ID: ${{ secrets.CLIENT_ID }}
CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }}
REFRESH_TOKEN: ${{ secrets.REFRESH_TOKEN }}
PUBLISH: ${{ inputs.publish }}
ZIP: d-party_${{ steps.version.outputs.new_version }}.zip
run: |
set -euo pipefail
# 1) refresh token -> access token
echo "::group::Exchange refresh_token for access_token"
token_resp=$(curl -sS -X POST https://oauth2.googleapis.com/token \
--data-urlencode "client_id=${CLIENT_ID}" \
--data-urlencode "client_secret=${CLIENT_SECRET}" \
--data-urlencode "refresh_token=${REFRESH_TOKEN}" \
--data-urlencode "grant_type=refresh_token")
# access_token / id_token はログに出さない
echo "${token_resp}" | jq 'del(.access_token, .id_token)'
echo "::endgroup::"
access_token=$(echo "${token_resp}" | jq -r '.access_token // empty')
if [ -z "${access_token}" ]; then
echo "::error::failed to obtain access_token (see token response above)"
exit 1
fi
# 2) Upload zip (PUT). 既存ドラフトを上書きする。
echo "::group::Upload ${ZIP} to item ${EXTENSION_ID}"
upload_resp=$(curl -sS -X PUT \
-H "Authorization: Bearer ${access_token}" \
-H "x-goog-api-version: 2" \
-T "${ZIP}" \
"https://www.googleapis.com/upload/chromewebstore/v1.1/items/${EXTENSION_ID}")
echo "${upload_resp}" | jq .
echo "::endgroup::"
upload_state=$(echo "${upload_resp}" | jq -r '.uploadState // empty')
if [ "${upload_state}" != "SUCCESS" ]; then
echo "::error::CWS upload failed (uploadState=${upload_state:-<none>})"
exit 1
fi
# 3) Publish (任意)。既定はアップロードのみ。
if [ "${PUBLISH}" = "true" ]; then
echo "::group::Publish item ${EXTENSION_ID}"
publish_resp=$(curl -sS -X POST \
-H "Authorization: Bearer ${access_token}" \
-H "x-goog-api-version: 2" \
-H "Content-Length: 0" \
"https://www.googleapis.com/chromewebstore/v1.1/items/${EXTENSION_ID}/publish")
echo "${publish_resp}" | jq .
echo "::endgroup::"
status=$(echo "${publish_resp}" | jq -r '.status[0] // empty')
case "${status}" in
OK|ITEM_PENDING_REVIEW) ;;
*)
echo "::error::CWS publish failed (status=${status:-<none>})"
exit 1
;;
esac
else
echo "publish=false: アップロードのみ完了。公開は Developer Dashboard から手動で行ってください。"
fi