Publish #20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| package: | |
| description: 'Package to release' | |
| required: true | |
| type: choice | |
| options: | |
| - hikkaku | |
| - create-hikkaku | |
| - vite-plugin-turbowarp-packager | |
| release_type: | |
| description: 'Version bump type' | |
| required: true | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| permissions: | |
| id-token: write | |
| contents: write | |
| jobs: | |
| publish: | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: publish-${{ inputs.package }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| id-token: write | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PACKAGE_NAME: ${{ inputs.package }} | |
| INPUT_RELEASE_TYPE: ${{ inputs.release_type }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Resolve release metadata | |
| id: metadata | |
| shell: bash | |
| run: | | |
| package="$PACKAGE_NAME" | |
| release_type="$INPUT_RELEASE_TYPE" | |
| if ! [[ "$package" =~ ^(hikkaku|create-hikkaku|vite-plugin-turbowarp-packager)$ ]]; then | |
| echo "Unsupported package: $package" | |
| exit 1 | |
| fi | |
| if ! [[ "$release_type" =~ ^(major|minor|patch)$ ]]; then | |
| echo "Invalid release_type: $release_type" | |
| echo "Supported values: major, minor, patch" | |
| exit 1 | |
| fi | |
| # Derive current version from latest tag for this package | |
| # If no tags exist, fall back to package.json version | |
| # Note: Uses git's version sorting which correctly handles semver including prereleases | |
| latest_tag=$(git tag -l "$package@*" --sort=-version:refname | head -n1) | |
| if [ -n "$latest_tag" ]; then | |
| # Extract version from tag (format: package@version) | |
| current_version="${latest_tag#$package@}" | |
| echo "Found latest tag: $latest_tag (version: $current_version)" | |
| else | |
| # No tags exist, use package.json version as starting point | |
| package_json_path="packages/$package/package.json" | |
| if [ ! -r "$package_json_path" ]; then | |
| echo "package.json not found or not readable: $package_json_path" | |
| exit 1 | |
| fi | |
| current_version="$(node -e "const fs=require('fs');const pkg=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));process.stdout.write(typeof pkg.version==='string'?pkg.version.trim():'')" "$package_json_path")" | |
| if [ -z "$current_version" ]; then | |
| echo "package.json does not contain a valid version field: $package_json_path" | |
| exit 1 | |
| fi | |
| echo "No existing tags found, using package.json version: $current_version" | |
| fi | |
| if ! [[ "$current_version" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)([.-][0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then | |
| echo "Invalid current package version: $current_version" | |
| exit 1 | |
| fi | |
| major="${BASH_REMATCH[1]}" | |
| minor="${BASH_REMATCH[2]}" | |
| patch="${BASH_REMATCH[3]}" | |
| case "$release_type" in | |
| major) | |
| major=$((major + 1)) | |
| minor=0 | |
| patch=0 | |
| ;; | |
| minor) | |
| minor=$((minor + 1)) | |
| patch=0 | |
| ;; | |
| patch) | |
| patch=$((patch + 1)) | |
| ;; | |
| esac | |
| version="$major.$minor.$patch" | |
| tag="$package@$version" | |
| if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then | |
| echo "Tag already exists: $tag" | |
| exit 1 | |
| fi | |
| if gh release view "$tag" >/dev/null 2>&1; then | |
| echo "Release already exists: $tag" | |
| exit 1 | |
| fi | |
| echo "package=$package" >> "$GITHUB_OUTPUT" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| - name: Ensure workflow runs on branch | |
| run: | | |
| if [[ '${{ github.ref_type }}' != 'branch' ]]; then | |
| echo "This workflow must run on a branch ref to push version updates." | |
| echo "Current ref_type: ${{ github.ref_type }}" | |
| exit 1 | |
| fi | |
| - name: Update package version | |
| run: | | |
| node -e "const fs=require('fs');const path='packages/${{ steps.metadata.outputs.package }}/package.json';const version='${{ steps.metadata.outputs.version }}';const pkg=JSON.parse(fs.readFileSync(path,'utf8'));pkg.version=version;const hasPrivate=Object.prototype.hasOwnProperty.call(pkg,'private');if(hasPrivate&&(pkg.name==='create-hikkaku'||pkg.name==='vite-plugin-turbowarp-packager')){pkg.private=false;}fs.writeFileSync(path,JSON.stringify(pkg,null,2)+'\n');" | |
| - name: Build hikkaku | |
| if: steps.metadata.outputs.package == 'hikkaku' | |
| run: bun run --filter hikkaku build | |
| - name: Build create-hikkaku | |
| if: steps.metadata.outputs.package == 'create-hikkaku' | |
| run: bun run --filter create-hikkaku build | |
| - name: Build vite-plugin-turbowarp-packager | |
| if: steps.metadata.outputs.package == 'vite-plugin-turbowarp-packager' | |
| run: bun run --filter vite-plugin-turbowarp-packager build | |
| - name: Build gpts zip | |
| if: steps.metadata.outputs.package == 'hikkaku' | |
| run: bun run --filter gpts-zip build | |
| - name: Resolve publish directory | |
| id: publish_dir | |
| shell: bash | |
| run: | | |
| case '${{ steps.metadata.outputs.package }}' in | |
| hikkaku) | |
| dir='packages/hikkaku/dist' | |
| ;; | |
| create-hikkaku) | |
| dir='packages/create-hikkaku' | |
| ;; | |
| vite-plugin-turbowarp-packager) | |
| dir='packages/vite-plugin-turbowarp-packager' | |
| ;; | |
| *) | |
| echo "Unsupported package: ${{ steps.metadata.outputs.package }}" | |
| exit 1 | |
| ;; | |
| esac | |
| echo "dir=$dir" >> "$GITHUB_OUTPUT" | |
| - name: Pack package tarball | |
| id: pack | |
| shell: bash | |
| run: | | |
| publish_dir='${{ steps.publish_dir.outputs.dir }}' | |
| tarball_output="$(cd "$publish_dir" && bun pm pack --quiet --destination "$RUNNER_TEMP")" | |
| tarball_output="$(echo "$tarball_output" | tr -d '\n')" | |
| if [[ "$tarball_output" = /* ]]; then | |
| tarball_path="$tarball_output" | |
| else | |
| tarball_path="$RUNNER_TEMP/$tarball_output" | |
| fi | |
| if [[ ! -f "$tarball_path" ]]; then | |
| echo "Tarball was not generated at expected path: $tarball_path" | |
| exit 1 | |
| fi | |
| echo "path=$tarball_path" >> "$GITHUB_OUTPUT" | |
| - name: Publish package tarball to npm | |
| run: npm publish '${{ steps.pack.outputs.path }}' --provenance --access public | |
| - name: Commit and push version update | |
| id: version_commit | |
| shell: bash | |
| run: | | |
| file_path="packages/${{ steps.metadata.outputs.package }}/package.json" | |
| git config user.name 'github-actions[bot]' | |
| git config user.email '41898282+github-actions[bot]@users.noreply.github.com' | |
| git add "$file_path" | |
| if git diff --cached --quiet; then | |
| echo "No version updates to commit." | |
| echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| git commit -m 'chore(release): bump ${{ steps.metadata.outputs.package }} to v${{ steps.metadata.outputs.version }}' | |
| git push origin "HEAD:${{ github.ref_name }}" | |
| echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | |
| - name: Create release with generated notes | |
| run: | | |
| if [[ '${{ steps.metadata.outputs.package }}' == 'hikkaku' ]]; then | |
| gh release create '${{ steps.metadata.outputs.tag }}' \ | |
| 'packages/gpts-zip/dist.zip#gpts.zip' \ | |
| --generate-notes \ | |
| --target '${{ steps.version_commit.outputs.sha }}' | |
| else | |
| gh release create '${{ steps.metadata.outputs.tag }}' \ | |
| --generate-notes \ | |
| --target '${{ steps.version_commit.outputs.sha }}' | |
| fi |