v1.1.3 #16
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: Full Release Pipeline | |
| on: | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version to release (e.g., 1.0.6)' | |
| required: true | |
| type: string | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write | |
| contents: write | |
| packages: write | |
| steps: | |
| # ============================================ | |
| # 1. Checkout and Setup | |
| # ============================================ | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: main | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Install AWS CLI | |
| run: pip install awscli | |
| - name: Configure AWS CLI for Yandex Cloud | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.YANDEX_STORAGE_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.YANDEX_STORAGE_SECRET_KEY }} | |
| run: | | |
| aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID | |
| aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY | |
| aws configure set default.region ru-central1 | |
| # ============================================ | |
| # 2. Extract version from release tag | |
| # ============================================ | |
| - name: Extract version from tag | |
| id: version | |
| run: | | |
| # Get version from release event or workflow_dispatch input | |
| if [ -n "${{ github.event.release.tag_name }}" ]; then | |
| TAG="${{ github.event.release.tag_name }}" | |
| VERSION="${TAG#v}" | |
| else | |
| VERSION="${{ github.event.inputs.version }}" | |
| TAG="v${VERSION}" | |
| fi | |
| echo "tag=$TAG" >> $GITHUB_OUTPUT | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "version_folder=v${VERSION}" >> $GITHUB_OUTPUT | |
| echo "📦 Release tag: $TAG" | |
| echo "📦 Version: $VERSION" | |
| # ============================================ | |
| # 3. Update package.json and package-lock.json | |
| # ============================================ | |
| - name: Update package.json version | |
| env: | |
| VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| echo "📝 Updating package.json to version $VERSION..." | |
| npm version $VERSION --no-git-tag-version --allow-same-version | |
| echo "✅ package.json updated" | |
| grep '"version"' package.json | head -1 | |
| # ============================================ | |
| # 4. Update src/core.js version (source of truth) | |
| # ============================================ | |
| # Note: prefetch.js and prefetch.esm.js are now generated by build.js | |
| # which reads version from package.json and replaces __VERSION__ placeholder | |
| - name: Update README.md version | |
| env: | |
| VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| echo "📝 Updating README.md to version $VERSION..." | |
| # Update version in JavaScript API example: // "1.0.X" | |
| sed -i "s|// \"[0-9]*\.[0-9]*\.[0-9]*\"|// \"${VERSION}\"|g" README.md | |
| echo "✅ README.md updated" | |
| grep -n "Prefetch.version" README.md | head -1 | |
| # ============================================ | |
| # 5. Build dist/prefetch.min.js + dist/prefetch.esm.min.js | |
| # ============================================ | |
| - name: Build minified versions | |
| run: | | |
| echo "🔨 Building dist/prefetch.min.js + dist/prefetch.esm.min.js..." | |
| npm run build | |
| echo "✅ Build complete" | |
| ls -la dist/ | |
| # ============================================ | |
| # 6. Calculate SRI Hash | |
| # ============================================ | |
| - name: Calculate SRI integrity hash | |
| id: sri | |
| run: | | |
| echo "🔐 Calculating SRI hash..." | |
| # IIFE версия | |
| SRI_HASH=$(openssl dgst -sha384 -binary dist/prefetch.min.js | openssl base64 -A) | |
| FULL_SRI="sha384-${SRI_HASH}" | |
| # ESM версия | |
| ESM_SRI_HASH=$(openssl dgst -sha384 -binary dist/prefetch.esm.min.js | openssl base64 -A) | |
| FULL_ESM_SRI="sha384-${ESM_SRI_HASH}" | |
| echo "sri_hash=$FULL_SRI" >> $GITHUB_OUTPUT | |
| echo "esm_sri_hash=$FULL_ESM_SRI" >> $GITHUB_OUTPUT | |
| echo "🔐 IIFE SRI Hash: $FULL_SRI" | |
| echo "🔐 ESM SRI Hash: $FULL_ESM_SRI" | |
| # ============================================ | |
| # 7. Upload to CDN bucket | |
| # ============================================ | |
| - name: Upload prefetch.min.js to CDN | |
| env: | |
| BUCKET: ${{ secrets.YANDEX_STORAGE_BUCKET_CDN }} | |
| ENDPOINT: ${{ secrets.YANDEX_STORAGE_ENDPOINT }} | |
| VERSION_FOLDER: ${{ steps.version.outputs.version_folder }} | |
| VERSION: ${{ steps.version.outputs.version }} | |
| SRI_HASH: ${{ steps.sri.outputs.sri_hash }} | |
| run: | | |
| echo "📤 Uploading to CDN: $BUCKET/$VERSION_FOLDER/prefetch.min.js" | |
| aws s3 cp dist/prefetch.min.js \ | |
| s3://${BUCKET}/${VERSION_FOLDER}/prefetch.min.js \ | |
| --endpoint-url ${ENDPOINT} \ | |
| --content-type "application/javascript; charset=utf-8" \ | |
| --cache-control "public, max-age=31536000, immutable" \ | |
| --metadata "version=${VERSION},sri-hash=${SRI_HASH}" | |
| echo "✅ Uploaded to: s3://${BUCKET}/${VERSION_FOLDER}/prefetch.min.js" | |
| # ============================================ | |
| # 8. Update www/index.html | |
| # ============================================ | |
| - name: Update index.html with new version and SRI | |
| env: | |
| VERSION: ${{ steps.version.outputs.version }} | |
| VERSION_FOLDER: ${{ steps.version.outputs.version_folder }} | |
| SRI_HASH: ${{ steps.sri.outputs.sri_hash }} | |
| run: | | |
| echo "📝 Updating www/index.html..." | |
| # Replace all version paths: /v1.0.X/ -> /vNEW/ | |
| sed -i "s|/v[0-9]*\.[0-9]*\.[0-9]*/|/${VERSION_FOLDER}/|g" www/index.html | |
| # Replace jsDelivr version: @prefetchru/prefetch@X.X.X -> @prefetchru/prefetch@NEW | |
| sed -i "s|@prefetchru/prefetch@[0-9]*\.[0-9]*\.[0-9]*|@prefetchru/prefetch@${VERSION}|g" www/index.html | |
| # Replace all SRI hashes (handles both plain HTML and syntax-highlighted code) | |
| # Pattern 1: integrity="sha384-..." | |
| sed -i "s|integrity=\"sha384-[^\"]*\"|integrity=\"${SRI_HASH}\"|g" www/index.html | |
| # Pattern 2: "sha384-..." in code spans (for syntax highlighting) | |
| sed -i "s|\"sha384-[^\"]*\"|\"${SRI_HASH}\"|g" www/index.html | |
| # Replace "Версия X.X.X" text | |
| sed -i "s|Версия [0-9]*\.[0-9]*\.[0-9]*|Версия ${VERSION}|g" www/index.html | |
| # Replace version in code examples: // "X.X.X" | |
| sed -i "s|// \"[0-9]*\.[0-9]*\.[0-9]*\"|// \"${VERSION}\"|g" www/index.html | |
| echo "✅ www/index.html updated" | |
| echo "" | |
| echo "📄 Updated lines:" | |
| grep -n "/${VERSION_FOLDER}/" www/index.html | head -5 | |
| grep -n "Версия ${VERSION}" www/index.html | head -2 | |
| # ============================================ | |
| # 9. Update www/sitemap.xml | |
| # ============================================ | |
| - name: Update sitemap.xml with current date | |
| run: | | |
| echo "📝 Updating www/sitemap.xml..." | |
| TODAY=$(date -u +"%Y-%m-%d") | |
| sed -i "s|<lastmod>[0-9-]*</lastmod>|<lastmod>${TODAY}</lastmod>|g" www/sitemap.xml | |
| echo "✅ www/sitemap.xml updated with date: $TODAY" | |
| cat www/sitemap.xml | |
| # ============================================ | |
| # 10. Minify index.html (only for deploy, not for commit) | |
| # ============================================ | |
| - name: Minify index.html for deploy | |
| run: | | |
| echo "🔨 Minifying www/index.html for deploy..." | |
| # Сохраняем оригинал для коммита (в репо всегда несжатый) | |
| cp www/index.html www/index.html.original | |
| # Размер до минификации | |
| BEFORE=$(stat -c%s www/index.html) | |
| echo "📄 Before: $BEFORE bytes" | |
| # Минификация HTML | |
| npx --yes html-minifier-terser \ | |
| --collapse-whitespace \ | |
| --preserve-line-breaks \ | |
| --remove-comments \ | |
| --remove-redundant-attributes \ | |
| --remove-script-type-attributes \ | |
| --remove-style-link-type-attributes \ | |
| --minify-css true \ | |
| --minify-js true \ | |
| --input-dir www \ | |
| --output-dir www \ | |
| --file-ext html | |
| # Размер после минификации | |
| AFTER=$(stat -c%s www/index.html) | |
| SAVED=$((BEFORE - AFTER)) | |
| PERCENT=$((SAVED * 100 / BEFORE)) | |
| echo "📄 After: $AFTER bytes" | |
| echo "✅ Saved: $SAVED bytes ($PERCENT%)" | |
| # ============================================ | |
| # 11. Upload changed www/ files to MAIN bucket | |
| # ============================================ | |
| - name: Upload changed www/ files to MAIN bucket | |
| env: | |
| BUCKET: ${{ secrets.YANDEX_STORAGE_BUCKET_MAIN }} | |
| ENDPOINT: ${{ secrets.YANDEX_STORAGE_ENDPOINT }} | |
| run: | | |
| echo "📤 Uploading changed www/ files to MAIN bucket: $BUCKET" | |
| # During release, only index.html and sitemap.xml are modified | |
| # Upload them directly instead of full sync | |
| for file in www/index.html www/sitemap.xml; do | |
| if [ -f "$file" ]; then | |
| S3_PATH="${file#www/}" | |
| echo " 📄 Uploading: $file → $S3_PATH" | |
| aws s3 cp "$file" "s3://${BUCKET}/${S3_PATH}" \ | |
| --endpoint-url ${ENDPOINT} | |
| fi | |
| done | |
| echo "✅ Changed files uploaded to MAIN bucket" | |
| - name: Verify MAIN bucket contents | |
| env: | |
| BUCKET: ${{ secrets.YANDEX_STORAGE_BUCKET_MAIN }} | |
| ENDPOINT: ${{ secrets.YANDEX_STORAGE_ENDPOINT }} | |
| run: | | |
| echo "📁 Contents of MAIN bucket:" | |
| aws s3 ls s3://${BUCKET}/ \ | |
| --endpoint-url ${ENDPOINT} \ | |
| --recursive \ | |
| --human-readable | |
| # ============================================ | |
| # 12. Restore original index.html for commit | |
| # ============================================ | |
| - name: Restore original index.html | |
| run: | | |
| echo "📄 Restoring original (unminified) www/index.html for commit..." | |
| mv www/index.html.original www/index.html | |
| echo "✅ Original restored" | |
| # ============================================ | |
| # 13. Commit changes back to repository | |
| # ============================================ | |
| - name: Commit version updates | |
| env: | |
| VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| # Add all files first (including gitignored with -f) | |
| # prefetch.js and prefetch.esm.js are in .gitignore — use -f to force add | |
| # dist/ is NOT committed — only used for CDN upload, npm publish, and release artifacts | |
| git add -f prefetch.js prefetch.esm.js | |
| git add package.json package-lock.json README.md www/index.html www/sitemap.xml | |
| # Check if there are staged changes | |
| if git diff --cached --quiet; then | |
| echo "ℹ️ No changes to commit" | |
| else | |
| git commit -m "chore: release v${VERSION} - update version, SRI hash, sitemap [skip ci]" | |
| git push origin main | |
| echo "✅ Changes committed and pushed" | |
| fi | |
| # ============================================ | |
| # 14. Create release artifacts | |
| # ============================================ | |
| - name: Create release artifacts | |
| env: | |
| SRI_HASH: ${{ steps.sri.outputs.sri_hash }} | |
| ESM_SRI_HASH: ${{ steps.sri.outputs.esm_sri_hash }} | |
| VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| echo "📦 Creating release artifacts..." | |
| # Create artifacts directory | |
| mkdir -p artifacts | |
| # Copy minified files | |
| cp dist/prefetch.min.js artifacts/ | |
| cp dist/prefetch.esm.min.js artifacts/ | |
| cd artifacts | |
| # IIFE version: MD5 + SRI + ZIP | |
| md5sum prefetch.min.js > prefetch.min.js.md5 | |
| echo "${SRI_HASH}" > prefetch.min.js.sri | |
| zip prefetch.min.js.zip prefetch.min.js prefetch.min.js.md5 prefetch.min.js.sri | |
| # ESM version: MD5 + SRI + ZIP | |
| md5sum prefetch.esm.min.js > prefetch.esm.min.js.md5 | |
| echo "${ESM_SRI_HASH}" > prefetch.esm.min.js.sri | |
| zip prefetch.esm.min.js.zip prefetch.esm.min.js prefetch.esm.min.js.md5 prefetch.esm.min.js.sri | |
| cd .. | |
| echo "✅ Artifacts created:" | |
| ls -la artifacts/ | |
| echo "" | |
| echo "📄 IIFE MD5:" | |
| cat artifacts/prefetch.min.js.md5 | |
| echo "📄 IIFE SRI:" | |
| cat artifacts/prefetch.min.js.sri | |
| echo "" | |
| echo "📄 ESM MD5:" | |
| cat artifacts/prefetch.esm.min.js.md5 | |
| echo "📄 ESM SRI:" | |
| cat artifacts/prefetch.esm.min.js.sri | |
| echo "" | |
| echo "📦 IIFE ZIP contents:" | |
| unzip -l artifacts/prefetch.min.js.zip | |
| echo "" | |
| echo "📦 ESM ZIP contents:" | |
| unzip -l artifacts/prefetch.esm.min.js.zip | |
| # ============================================ | |
| # 15. Upload artifacts to release | |
| # ============================================ | |
| - name: Upload release assets | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| echo "📤 Uploading assets to release..." | |
| TAG="${{ steps.version.outputs.tag }}" | |
| gh release upload "$TAG" \ | |
| artifacts/prefetch.min.js.zip \ | |
| artifacts/prefetch.esm.min.js.zip \ | |
| --clobber | |
| echo "✅ Assets uploaded to release" | |
| - name: Update release notes with SRI hash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SRI_HASH: ${{ steps.sri.outputs.sri_hash }} | |
| run: | | |
| echo "📝 Updating release notes..." | |
| # Get current release body | |
| TAG="${{ steps.version.outputs.tag }}" | |
| CURRENT_BODY=$(gh release view "$TAG" --json body -q '.body') | |
| # Create notes file with only SRI | |
| { | |
| echo "" | |
| echo "---" | |
| echo "" | |
| echo "## Integrity (SRI) IIFE — prefetch.min.js" | |
| echo "" | |
| echo '```' | |
| echo "${SRI_HASH}" | |
| echo '```' | |
| } > /tmp/release_notes.md | |
| # Combine current body with new notes | |
| echo "${CURRENT_BODY}" > /tmp/full_notes.md | |
| cat /tmp/release_notes.md >> /tmp/full_notes.md | |
| # Update release | |
| gh release edit "$TAG" --notes-file /tmp/full_notes.md | |
| echo "✅ Release notes updated with SRI hash" | |
| # ============================================ | |
| # 16. Publish to npm | |
| # ============================================ | |
| - name: Remove auth token for OIDC | |
| run: | | |
| # Remove authToken from .npmrc to allow OIDC authentication | |
| sed -i '/_authToken/d' $NPM_CONFIG_USERCONFIG 2>/dev/null || true | |
| - name: Publish to npm (OIDC Trusted Publishing) | |
| run: npm publish --access public --provenance | |
| continue-on-error: true # Don't fail if version already exists | |
| # ============================================ | |
| # 17. Publish to GitHub Packages | |
| # ============================================ | |
| - name: Setup for GitHub Packages | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| registry-url: 'https://npm.pkg.github.com' | |
| scope: '@prefetch-ru' | |
| - name: Update package name for GitHub Packages | |
| run: npm pkg set name="@prefetch-ru/prefetch" | |
| - name: Publish to GitHub Packages | |
| run: npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| continue-on-error: true | |
| # ============================================ | |
| # Summary | |
| # ============================================ | |
| - name: Release Summary | |
| env: | |
| VERSION: ${{ steps.version.outputs.version }} | |
| VERSION_FOLDER: ${{ steps.version.outputs.version_folder }} | |
| SRI_HASH: ${{ steps.sri.outputs.sri_hash }} | |
| BUCKET_CDN: ${{ secrets.YANDEX_STORAGE_BUCKET_CDN }} | |
| BUCKET_MAIN: ${{ secrets.YANDEX_STORAGE_BUCKET_MAIN }} | |
| run: | | |
| echo "" | |
| echo "==========================================" | |
| echo "🎉 Release v${VERSION} Complete!" | |
| echo "==========================================" | |
| echo "" | |
| echo "📦 Version: ${VERSION}" | |
| echo "🔐 SRI Hash: ${SRI_HASH}" | |
| echo "" | |
| echo "📁 CDN: s3://${BUCKET_CDN}/${VERSION_FOLDER}/prefetch.min.js" | |
| echo "📁 Main: s3://${BUCKET_MAIN}/ (www/ synced)" | |
| echo "" | |
| echo "📄 HTML:" | |
| echo "<script src=\"//prefetch.ru/${VERSION_FOLDER}/prefetch.min.js\"" | |
| echo " integrity=\"${SRI_HASH}\"" | |
| echo " crossorigin=\"anonymous\"></script>" | |
| echo "" | |
| echo "==========================================" |