Merge pull request #38 from keyqcloud/fix/version-literal-sync #39
Workflow file for this run
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: Release | |
| # Tag-triggered. Builds minified bundles + source maps from kyte-source.js, | |
| # uploads to S3, invalidates CloudFront, and creates a GitHub Release with | |
| # notes extracted from CHANGELOG.md. | |
| # | |
| # The version comes from the tag (refs/tags/v2.0.0 → 2.0.0). CHANGELOG.md | |
| # must have a `## <version>` section as the first H2 — the script extracts | |
| # everything between that and the next `## ` as release notes. | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write # needed for softprops/action-gh-release | |
| # GitHub force-migrates JavaScript actions to Node.js 24 on 2026-06-02. | |
| # Opting in early so the migration is a no-op for us; covers the actions | |
| # whose latest major (aws-actions/configure-aws-credentials@v4, | |
| # softprops/action-gh-release@v2) doesn't yet have a Node-24-native bump. | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| release: | |
| name: Build, deploy, and release | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out source code | |
| uses: actions/checkout@v5 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: '20' | |
| - name: Install terser | |
| run: npm install -g terser | |
| - name: Extract version from tag | |
| id: version | |
| run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT" | |
| - name: Verify CHANGELOG.md matches tag | |
| run: | | |
| VERSION="${{ steps.version.outputs.VERSION }}" | |
| CHANGELOG_VERSION=$(awk '/^## /{print $2; exit}' CHANGELOG.md) | |
| if [ "$CHANGELOG_VERSION" != "$VERSION" ]; then | |
| echo "::error::Tag v$VERSION does not match top of CHANGELOG.md (## $CHANGELOG_VERSION)." | |
| exit 1 | |
| fi | |
| - name: Build minified bundles with source maps | |
| run: | | |
| VERSION="${{ steps.version.outputs.VERSION }}" | |
| YEAR=$(date +'%Y') | |
| # Force the runtime VERSION literal to the tag. Single source of | |
| # truth is the git tag (same as the copyright header below). | |
| # release-please's x-release-please-version annotation keeps the | |
| # committed source in sync; this is the belt-and-suspenders so the | |
| # SHIPPED bundle can never drift from the tag even if that slips | |
| # (which is exactly how v2.1.0 went out logging "2.0.2"). | |
| sed -i -E "s/(static VERSION *= *['\"])[0-9]+\.[0-9]+\.[0-9]+(['\"])/\1${VERSION}\2/" kyte-source.js | |
| STAMPED=$(grep -oE "static VERSION *= *['\"][0-9.]+['\"]" kyte-source.js) | |
| echo "Stamped: ${STAMPED}" | |
| if ! echo "${STAMPED}" | grep -q "'${VERSION}'"; then | |
| echo "::error::Failed to stamp VERSION literal to ${VERSION} (got: ${STAMPED})." | |
| exit 1 | |
| fi | |
| # Two builds: | |
| # kyte.js — minified, with `//# sourceMappingURL=kyte.js.map` | |
| # appended by terser; pairs with kyte.js.map for | |
| # customer debugging. | |
| # kyte.min.js — minified, no source-map reference; for callers | |
| # that don't want the .map fetch (size-sensitive). | |
| terser kyte-source.js \ | |
| -c -m \ | |
| --source-map "url='kyte.js.map'" \ | |
| -o kyte.js | |
| terser kyte-source.js \ | |
| -c -m \ | |
| -o kyte.min.js | |
| # Prepend copyright notice to both. Source map stays untouched — | |
| # browsers tolerate a leading comment in the .js but not in JSON. | |
| cat > copyright.txt <<EOF | |
| /** | |
| * Copyright 2020-${YEAR} KeyQ, Inc. | |
| * MIT License — https://opensource.org/licenses/MIT | |
| * KyteJS v${VERSION} | |
| **/ | |
| EOF | |
| cat copyright.txt kyte.js > tmp && mv tmp kyte.js | |
| cat copyright.txt kyte.min.js > tmp && mv tmp kyte.min.js | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: ${{ secrets.AWS_REGION }} | |
| - name: Upload stable bundles to S3 | |
| run: | | |
| aws s3 cp kyte.js s3://${{ secrets.S3_BUCKET }}/kyte/js/stable/kyte.js --content-type application/javascript | |
| aws s3 cp kyte.min.js s3://${{ secrets.S3_BUCKET }}/kyte/js/stable/kyte.min.js --content-type application/javascript | |
| aws s3 cp kyte.js.map s3://${{ secrets.S3_BUCKET }}/kyte/js/stable/kyte.js.map --content-type application/json | |
| - name: Upload version-pinned archive bundle to S3 | |
| run: | | |
| VERSION="${{ steps.version.outputs.VERSION }}" | |
| aws s3 cp kyte.js "s3://${{ secrets.S3_BUCKET }}/kyte/js/archive/kyte-${VERSION}.js" --content-type application/javascript | |
| aws s3 cp kyte.js.map "s3://${{ secrets.S3_BUCKET }}/kyte/js/archive/kyte-${VERSION}.js.map" --content-type application/json | |
| - name: Invalidate CloudFront cache | |
| run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CF_DISTRIBUTION_ID }} --paths '/*' | |
| - name: Extract release notes from CHANGELOG.md | |
| id: notes | |
| run: | | |
| VERSION="${{ steps.version.outputs.VERSION }}" | |
| # Capture everything between `## $VERSION` and the next `## ` line. | |
| awk -v v="^## ${VERSION}$" ' | |
| $0 ~ v { capture=1; next } | |
| /^## / && capture { exit } | |
| capture { print } | |
| ' CHANGELOG.md > release-notes.md | |
| # Sanity check: if release-notes.md is empty the GitHub Release | |
| # would be blank. Fail loud rather than ship empty notes. | |
| if [ ! -s release-notes.md ]; then | |
| echo "::error::Could not extract release notes for v$VERSION from CHANGELOG.md" | |
| exit 1 | |
| fi | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| name: KyteJS v${{ steps.version.outputs.VERSION }} | |
| body_path: release-notes.md | |
| files: | | |
| kyte.js | |
| kyte.min.js | |
| kyte.js.map | |
| draft: false | |
| prerelease: false |