Skip to content

Release v0.1.0

Release v0.1.0 #87

Workflow file for this run

#/
# @license Apache-2.0
#
# Copyright (c) 2022 The Stdlib Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#/
# Workflow name:
name: productionize
# Workflow triggers:
on:
# Run workflow when a new commit is pushed to the main branch:
push:
branches:
- main
# Allow the workflow to be manually run:
workflow_dispatch:
inputs:
require-passing-tests:
description: 'Require passing tests for creating bundles'
type: boolean
default: true
# Run workflow upon completion of `publish` workflow run:
workflow_run:
workflows: ["publish"]
types: [completed]
# Concurrency group to prevent multiple concurrent executions:
concurrency:
group: productionize
cancel-in-progress: true
# Workflow jobs:
jobs:
# Define a job to create a production build...
productionize:
# Define display name:
name: 'Productionize'
# Define the type of virtual host machine:
runs-on: 'ubuntu-latest'
# Define the sequence of job steps...
steps:
# Checkout main branch of repository:
- name: 'Checkout main branch'
uses: actions/checkout@v3
with:
ref: main
# Install Node.js:
- name: 'Install Node.js'
uses: actions/setup-node@v3
with:
node-version: 16
timeout-minutes: 5
# Create production branch:
- name: 'Create production branch'
run: |
git checkout -b production
# Transform error messages:
- name: 'Transform error messages'
id: transform-error-messages
uses: stdlib-js/transform-errors-action@main
# Change `@stdlib/string-format` to `@stdlib/error-tools-fmtprodmsg` in package.json if the former is a dependency, otherwise insert it as a dependency:
- name: 'Update dependencies in package.json'
run: |
PKG_VERSION=$(npm view @stdlib/error-tools-fmtprodmsg version)
if grep -q '"@stdlib/string-format"' package.json; then
sed -i "s/\"@stdlib\/string-format\": \"^.*\"/\"@stdlib\/error-tools-fmtprodmsg\": \"^$PKG_VERSION\"/g" package.json
else
node -e "var pkg = require( './package.json' ); pkg.dependencies[ '@stdlib/error-tools-fmtprodmsg' ] = '^$PKG_VERSION'; require( 'fs' ).writeFileSync( 'package.json', JSON.stringify( pkg, null, 2 ) );"
fi
# Configure git:
- name: 'Configure git'
run: |
git config --local user.email "[email protected]"
git config --local user.name "stdlib-bot"
# Commit changes:
- name: 'Commit changes'
run: |
git add -A
git commit -m "Transform error messages"
# Push changes:
- name: 'Push changes'
run: |
SLUG=${{ github.repository }}
echo "Pushing changes to $SLUG..."
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" production --force
# Define a job for running tests of the productionized code...
test:
# Define a display name:
name: 'Run Tests'
# Define the type of virtual host machine:
runs-on: 'ubuntu-latest'
# Indicate that this job depends on the prior job finishing:
needs: productionize
# Run this job regardless of the outcome of the prior job:
if: always()
# Define the sequence of job steps...
steps:
# Checkout the repository:
- name: 'Checkout repository'
if: ${{ github.event.inputs.require-passing-tests == 'true' }}
uses: actions/checkout@v3
with:
# Use the `production` branch:
ref: production
# Install Node.js:
- name: 'Install Node.js'
if: ${{ github.event.inputs.require-passing-tests == 'true' }}
uses: actions/setup-node@v3
with:
node-version: 16
timeout-minutes: 5
# Install dependencies:
- name: 'Install production and development dependencies'
if: ${{ github.event.inputs.require-passing-tests == 'true' }}
id: install
run: |
npm install || npm install || npm install
timeout-minutes: 15
# Build native add-on if present:
- name: 'Build native add-on (if present)'
if: ${{ github.event.inputs.require-passing-tests == 'true' }}
run: |
if [ -f "binding.gyp" ]; then
npm install node-gyp --no-save && ./node_modules/.bin/node-gyp rebuild
fi
# Run tests:
- name: 'Run tests'
if: ${{ github.event.inputs.require-passing-tests == 'true' }}
id: tests
run: |
npm test || npm test || npm test
# Define job to create a bundle for use in Deno...
deno:
# Define display name:
name: 'Create Deno bundle'
# Define the type of virtual host machine on which to run the job:
runs-on: ubuntu-latest
# Indicate that this job depends on the test job finishing:
needs: test
# Define the sequence of job steps...
steps:
# Checkout the repository:
- name: 'Checkout repository'
uses: actions/checkout@v3
# Configure git:
- name: 'Configure git'
run: |
git config --local user.email "[email protected]"
git config --local user.name "stdlib-bot"
# Check if remote `deno` branch exists:
- name: 'Check if remote `deno` branch exists'
id: deno-branch-exists
continue-on-error: true
run: |
git fetch --all
git ls-remote --exit-code --heads origin deno
if [ $? -eq 0 ]; then
echo "remote-exists=true" >> $GITHUB_OUTPUT
else
echo "remote-exists=false" >> $GITHUB_OUTPUT
fi
# If `deno` exists, delete everything in branch and merge `production` into it
- name: 'If `deno` exists, delete everything in branch and merge `production` into it'
if: steps.deno-branch-exists.outputs.remote-exists
run: |
git checkout -b deno origin/deno
find . -type 'f' | grep -v -e ".git/" -e "package.json" -e "README.md" -e "LICENSE" -e "CONTRIBUTORS" -e "NOTICE" | xargs -r rm
find . -mindepth 1 -type 'd' | grep -v -e ".git" | xargs -r rm -rf
git add -A
git commit -m "Remove files" --allow-empty
git config merge.theirs.name 'simulate `-s theirs`'
git config merge.theirs.driver 'cat %B > %A'
GIT_CONFIG_PARAMETERS="'merge.default=theirs'" git merge origin/production --allow-unrelated-histories
# Copy files from `production` branch if necessary:
git checkout origin/production -- .
if [ -n "$(git status --porcelain)" ]; then
git add -A
git commit -m "Auto-generated commit"
fi
# If `deno` does not exist, create `deno` branch:
- name: 'If `deno` does not exist, create `deno` branch'
if: ${{ steps.deno-branch-exists.outputs.remote-exists == false }}
run: |
git checkout production
git checkout -b deno
# Copy files to deno directory:
- name: 'Copy files to deno directory'
run: |
mkdir -p deno
cp README.md LICENSE CONTRIBUTORS NOTICE ./deno
# Copy TypeScript definitions to deno directory:
if [ -d index.d.ts ]; then
cp index.d.ts ./deno/index.d.ts
fi
if [ -e ./docs/types/index.d.ts ]; then
cp ./docs/types/index.d.ts ./deno/mod.d.ts
fi
# Install Node.js:
- name: 'Install Node.js'
uses: actions/setup-node@v3
with:
node-version: 16
timeout-minutes: 5
# Install dependencies:
- name: Install production and development dependencies
id: install
run: |
npm install || npm install || npm install
timeout-minutes: 15
# Bundle package for use in Deno:
- name: 'Bundle package for Deno'
id: deno-bundle
uses: stdlib-js/bundle-action@main
with:
target: 'deno'
# Rewrite file contents:
- name: 'Rewrite file contents'
run: |
# Replace links to other packages with links to the deno branch:
find ./deno -type f -name '*.md' -print0 | xargs -0 sed -Ei "/\/tree\/main/b; /^\[@stdlib[^:]+: https:\/\/github.com\/stdlib-js\// s/(.*)/\\1\/tree\/deno/";
# Replace reference to `@stdlib/types` with CDN link:
find ./deno -type f -name '*.ts' -print0 | xargs -0 sed -Ei "s/\/\/\/ <reference types=\"@stdlib\/types\"\/>/\/\/\/ <reference types=\"https:\/\/cdn.jsdelivr.net\/gh\/stdlib-js\/types@main\/index.d.ts\"\/>/g"
# Change wording of project description to avoid reference to JavaScript and Node.js:
find ./deno -type f -name '*.md' -print0 | xargs -0 sed -Ei "s/a standard library for JavaScript and Node.js, /a standard library /g"
# Rewrite all `require()`s to use jsDelivr links:
find ./deno -type f -name '*.md' -print0 | xargs -0 sed -Ei "/require\( '@stdlib\// {
s/(var|let|const)\s+([a-z0-9_]+)\s+=\s*require\( '([^']+)' \);/import \2 from \'\3\';/i
s/@stdlib/https:\/\/cdn.jsdelivr.net\/gh\/stdlib-js/
s/';/@deno\/mod.js';/
}"
# Rewrite first `import` to show importing of named exports if available:
exports=$(cat lib/index.js | \
grep -E 'setReadOnly\(.*,.*,.*\)' | \
sed -E 's/setReadOnly\((.*),(.*),(.*)\);/\2/' | \
sed -E "s/'//g" | \
sort)
if [ -n "$exports" ]; then
find ./deno -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/\`\`\`javascript\nimport\s+([a-zA-Z0-9_]+)\s+from\s*'([^']+)';\n\`\`\`/\`\`\`javascript\nimport \1 from '\2';\n\`\`\`\n\nYou can also import the following named exports from the package:\n\n\`\`\`javascript\nimport { $(echo $exports | sed -E 's/ /, /g') } from '\2';\n\`\`\`/"
fi
# Remove `installation`, `cli`, and `c` sections:
find ./deno -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/<section class=\"installation\">[^<]+<\/section>//g;"
find ./deno -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"cli\">[\s\S]+<\!\-\- \/.cli \-\->//g"
find ./deno -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"c\">[\s\S]+<\!\-\- \/.c \-\->//g"
# Create package.json file for deno branch:
jq --indent 2 '{"name": .name, "version": .version, "description": .description, "license": .license, "type": "module", "main": "./mod.js", "homepage": .homepage, "repository": .repository, "bugs": .bugs, "keywords": .keywords, "funding": .funding}' package.json > ./deno/package.json
# Delete everything in current directory aside from deno folder:
- name: 'Delete everything in current directory aside from deno folder'
run: |
find . -type 'f' | grep -v -e "deno" -e ".git/" | xargs -r rm
find . -mindepth 1 -type 'd' | grep -v -e "deno" -e ".git" | xargs -r rm -rf
# Move deno directory to root:
- name: 'Move deno directory to root'
run: |
mv ./deno/* .
rmdir ./deno
# Commit changes:
- name: 'Commit changes'
run: |
git add -A
git commit -m "Auto-generated commit"
# Push changes to `deno` branch:
- name: 'Push changes to `deno` branch'
run: |
SLUG=${{ github.repository }}
echo "Pushing changes to $SLUG..."
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" deno
# Send status to Slack channel if job fails:
- name: 'Send status to Slack channel in case of failure'
uses: act10ns/slack@v2
with:
status: ${{ job.status }}
steps: ${{ toJson(steps) }}
channel: '#npm-ci'
if: failure()
# Define job to create a UMD bundle...
umd:
# Define display name:
name: 'Create UMD bundle'
# Define the type of virtual host machine on which to run the job:
runs-on: ubuntu-latest
# Indicate that this job depends on the test job finishing:
needs: test
# Define the sequence of job steps...
steps:
# Checkout the repository:
- name: 'Checkout repository'
uses: actions/checkout@v3
# Configure git:
- name: 'Configure git'
run: |
git config --local user.email "[email protected]"
git config --local user.name "stdlib-bot"
# Check if remote `umd` branch exists:
- name: 'Check if remote `umd` branch exists'
id: umd-branch-exists
continue-on-error: true
run: |
git fetch --all
git ls-remote --exit-code --heads origin umd
if [ $? -eq 0 ]; then
echo "remote-exists=true" >> $GITHUB_OUTPUT
else
echo "remote-exists=false" >> $GITHUB_OUTPUT
fi
# If `umd` exists, delete everything in branch and merge `production` into it
- name: 'If `umd` exists, delete everything in branch and merge `production` into it'
if: steps.umd-branch-exists.outputs.remote-exists
run: |
git checkout -b umd origin/umd
find . -type 'f' | grep -v -e ".git/" -e "package.json" -e "README.md" -e "LICENSE" -e "CONTRIBUTORS" -e "NOTICE" | xargs -r rm
find . -mindepth 1 -type 'd' | grep -v -e ".git" | xargs -r rm -rf
git add -A
git commit -m "Remove files" --allow-empty
git config merge.theirs.name 'simulate `-s theirs`'
git config merge.theirs.driver 'cat %B > %A'
GIT_CONFIG_PARAMETERS="'merge.default=theirs'" git merge origin/production --allow-unrelated-histories
# Copy files from `production` branch if necessary:
git checkout origin/production -- .
if [ -n "$(git status --porcelain)" ]; then
git add -A
git commit -m "Auto-generated commit"
fi
# If `umd` does not exist, create `umd` branch:
- name: 'If `umd` does not exist, create `umd` branch'
if: ${{ steps.umd-branch-exists.outputs.remote-exists == false }}
run: |
git checkout production
git checkout -b umd
# Copy files to umd directory:
- name: 'Copy files to umd directory'
run: |
mkdir -p umd
cp README.md LICENSE CONTRIBUTORS NOTICE ./umd
# Install Node.js
- name: 'Install Node.js'
uses: actions/setup-node@v3
with:
node-version: 16
timeout-minutes: 5
# Install dependencies:
- name: 'Install production and development dependencies'
id: install
run: |
npm install || npm install || npm install
timeout-minutes: 15
# Extract alias:
- name: 'Extract alias'
id: extract-alias
run: |
alias=$(grep -E 'require\(' README.md | head -n 1 | sed -E 's/^var ([a-zA-Z0-9_]+) = .+/\1/')
echo "alias=${alias}" >> $GITHUB_OUTPUT
# Create Universal Module Definition (UMD) Node.js bundle:
- name: 'Create Universal Module Definition (UMD) Node.js bundle'
id: umd-bundle-node
uses: stdlib-js/bundle-action@main
with:
target: 'umd-node'
alias: ${{ steps.extract-alias.outputs.alias }}
# Create Universal Module Definition (UMD) browser bundle:
- name: 'Create Universal Module Definition (UMD) browser bundle'
id: umd-bundle-browser
uses: stdlib-js/bundle-action@main
with:
target: 'umd-browser'
alias: ${{ steps.extract-alias.outputs.alias }}
# Rewrite file contents:
- name: 'Rewrite file contents'
run: |
# Replace links to other packages with links to the umd branch:
find ./umd -type f -name '*.md' -print0 | xargs -0 sed -Ei "/\/tree\/main/b; /^\[@stdlib[^:]+: https:\/\/github.com\/stdlib-js\// s/(.*)/\\1\/tree\/umd/";
# Remove `installation`, `cli`, and `c` sections:
find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/<section class=\"installation\">[^<]+<\/section>//g;"
find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"cli\">[\s\S]+<\!\-\- \/.cli \-\->//g"
find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"c\">[\s\S]+<\!\-\- \/.c \-\->//g"
# Rewrite first `require()` to show consumption of the UMD bundle in Observable and via a `script` tag:
find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/\`\`\`javascript\n(var|let|const)\s+([a-zA-Z0-9_]+)\s+=\s*require\( '\@stdlib\/([^']+)' \);\n\`\`\`/To use in Observable,\n\n\`\`\`javascript\n\2 = require\( 'https:\/\/cdn.jsdelivr.net\/gh\/stdlib-js\/\3\@umd\/browser.js' \)\n\`\`\`\n\nTo vendor stdlib functionality and avoid installing dependency trees for Node.js, you can use the UMD server build:\n\n\`\`\`javascript\nvar \2 = require\( 'path\/to\/vendor\/umd\/\3\/index.js' \)\n\`\`\`\n\nTo include the bundle in a webpage,\n\n\`\`\`html\n<script type=\"text\/javascript\" src=\"https:\/\/cdn.jsdelivr.net\/gh\/stdlib-js\/\3\@umd\/browser.js\"><\/script>\n\`\`\`\n\nIf no recognized module system is present, access bundle contents via the global scope:\n\n\`\`\`html\n<script type=\"text\/javascript\">\n window.\2;\n<\/script>\n\`\`\`/"
# Rewrite examples section to be a HTML file:
find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/\#\# Examples([\s\S]*)\`\`\`javascript([\s\S]+?)\`\`\`/\#\# Examples\1\`\`\`html\n<\!DOCTYPE html>\n<html lang=\"en\">\n<body>\n<script type=\"text\/javascript\">\2\n<\/script>\n<\/body>\n<\/html>\n\`\`\`/"
# Rewrite all `require()`s in the examples section as `script` tags loading the respective UMD bundle:
find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "1 while s/<script type=\"text\/javascript\">\n(var|let|const)\s+([a-zA-Z0-9_]+)\s+=\s*require\( '\@stdlib\/([^']+)' \);?/<script type=\"text\/javascript\" src=\"https:\/\/cdn.jsdelivr.net\/gh\/stdlib-js\/\3\@umd\/browser.js\"><\/script>\n<script type=\"text\/javascript\">/g"
# Wrap contents of `<script type="text/javascript">` tag contents in an IIFE:
find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/<script type=\"text\/javascript\">([\s\S]+?)<\/script>/<script type=\"text\/javascript\">\n\(function \(\) {\1}\)\(\);\n<\/script>/g"
# Create package.json file for umd branch:
jq --indent 2 '{"name": .name, "version": .version, "description": .description, "license": .license, "main": "./index.js", "homepage": .homepage, "repository": .repository, "bugs": .bugs, "keywords": .keywords, "funding": .funding}' package.json > ./umd/package.json
# Delete everything in current directory aside from umd folder:
- name: 'Delete everything in current directory aside from umd folder'
run: |
find . -type 'f' | grep -v -e "umd" -e ".git/" | xargs -r rm
find . -mindepth 1 -type 'd' | grep -v -e "umd" -e ".git" | xargs -r rm -rf
# Move umd directory to root:
- name: 'Move umd directory to root'
run: |
mv ./umd/* .
rmdir ./umd
# Commit changes:
- name: 'Commit changes'
run: |
git add -A
git commit -m "Auto-generated commit"
# Push changes to `umd` branch:
- name: 'Push changes to `umd` branch'
run: |
SLUG=${{ github.repository }}
echo "Pushing changes to $SLUG..."
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" umd
# Send status to Slack channel if job fails:
- name: 'Send status to Slack channel in case of failure'
uses: act10ns/slack@v2
with:
status: ${{ job.status }}
steps: ${{ toJson(steps) }}
channel: '#npm-ci'
if: failure()
# Define job to create ES module build...
esm:
# Define display name:
name: 'Create ES module build'
# Define the type of virtual host machine on which to run the job:
runs-on: ubuntu-latest
# Indicate that this job depends on the test job finishing:
needs: test
# Define the sequence of job steps...
steps:
# Checkout the repository:
- name: 'Checkout repository'
uses: actions/checkout@v3
# Configure git:
- name: 'Configure git'
run: |
git config --local user.email "[email protected]"
git config --local user.name "stdlib-bot"
# Check if remote `esm` branch exists:
- name: 'Check if remote `esm` branch exists'
id: esm-branch-exists
continue-on-error: true
run: |
git fetch --all
git ls-remote --exit-code --heads origin esm
if [ $? -eq 0 ]; then
echo "remote-exists=true" >> $GITHUB_OUTPUT
else
echo "remote-exists=false" >> $GITHUB_OUTPUT
fi
# If `esm` exists, delete everything in branch and merge `production` into it
- name: 'If `esm` exists, delete everything in branch and merge `production` into it'
if: steps.esm-branch-exists.outputs.remote-exists
run: |
git checkout -b esm origin/esm
find . -type 'f' | grep -v -e ".git/" -e "package.json" -e "README.md" -e "LICENSE" -e "CONTRIBUTORS" -e "NOTICE" | xargs -r rm
find . -mindepth 1 -type 'd' | grep -v -e ".git" | xargs -r rm -rf
git add -A
git commit -m "Remove files" --allow-empty
git config merge.theirs.name 'simulate `-s theirs`'
git config merge.theirs.driver 'cat %B > %A'
GIT_CONFIG_PARAMETERS="'merge.default=theirs'" git merge origin/production --allow-unrelated-histories
# Copy files from `production` branch if necessary:
git checkout origin/production -- .
if [ -n "$(git status --porcelain)" ]; then
git add -A
git commit -m "Auto-generated commit"
fi
# If `esm` does not exist, create `esm` branch:
- name: 'If `esm` does not exist, create `esm` branch'
if: ${{ steps.esm-branch-exists.outputs.remote-exists == false }}
run: |
git checkout production
git checkout -b esm
# Copy files to esm directory:
- name: 'Copy files to esm directory'
run: |
mkdir -p esm
cp README.md LICENSE CONTRIBUTORS NOTICE ./esm
# Copy TypeScript definitions to esm directory:
if [ -e ./docs/types/index.d.ts ]; then
cp ./docs/types/index.d.ts ./esm/index.d.ts
fi
if [ -d index.d.ts ]; then
cp index.d.ts ./esm/index.d.ts
fi
# Install Node.js:
- name: 'Install Node.js'
uses: actions/setup-node@v3
with:
node-version: 16
timeout-minutes: 5
# Install dependencies:
- name: 'Install production and development dependencies'
id: install
run: |
npm install || npm install || npm install
timeout-minutes: 15
# Create ES Module (ESM) bundle:
- name: 'Create ES Module (ESM) bundle'
id: esm-bundle
uses: stdlib-js/bundle-action@main
with:
target: 'esm'
# Rewrite file contents:
- name: 'Rewrite file contents'
run: |
# Replace links to other packages with links to the esm branch:
find ./esm -type f -name '*.md' -print0 | xargs -0 sed -Ei "/\/tree\/main/b; /^\[@stdlib[^:]+: https:\/\/github.com\/stdlib-js\// s/(.*)/\\1\/tree\/esm/";
# Replace reference to `@stdlib/types` with esm link:
find ./esm -type f -name '*.ts' -print0 | xargs -0 sed -Ei "s/\/\/\/ <reference types=\"@stdlib\/types\"\/>/\/\/\/ <reference types=\"https:\/\/cdn.jsdelivr.net\/gh\/stdlib-js\/types@esm\/index.d.ts\"\/>/g"
# Change wording of project description to avoid reference to JavaScript and Node.js:
find ./esm -type f -name '*.md' -print0 | xargs -0 sed -Ei "s/a standard library for JavaScript and Node.js, /a standard library /g"
# Rewrite all `require()`s to use jsDelivr links:
find ./esm -type f -name '*.md' -print0 | xargs -0 sed -Ei "/require\( '@stdlib\// {
s/(var|let|const)\s+([a-z0-9_]+)\s+=\s*require\( '([^']+)' \);/import \2 from \'\3\';/i
s/@stdlib/https:\/\/cdn.jsdelivr.net\/gh\/stdlib-js/
s/';/@esm\/index.mjs';/
}"
# Rewrite first `import` to show importing of named exports if available:
exports=$(cat lib/index.js | \
grep -E 'setReadOnly\(.*,.*,.*\)' | \
sed -E 's/setReadOnly\((.*),(.*),(.*)\);/\2/' | \
sed -E "s/'//g" | \
sort)
if [ -n "$exports" ]; then
find ./esm -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/\`\`\`javascript\nimport\s+([a-zA-Z0-9_]+)\s+from\s*'([^']+)';\n\`\`\`/\`\`\`javascript\nimport \1 from '\2';\n\`\`\`\n\nYou can also import the following named exports from the package:\n\n\`\`\`javascript\nimport { $(echo $exports | sed -E 's/ /, /g') } from '\2';\n\`\`\`/"
fi
# Remove `installation`, `cli`, and `c` sections:
find ./esm -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/<section class=\"installation\">[^<]+<\/section>//g;"
find ./esm -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"cli\">[\s\S]+<\!\-\- \/.cli \-\->//g"
find ./esm -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"c\">[\s\S]+<\!\-\- \/.c \-\->//g"
# Rewrite examples section to be a HTML file:
find ./esm -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/\#\# Examples([\s\S]*)\`\`\`javascript([\s\S]+?)\`\`\`/\#\# Examples\1\`\`\`html\n<\!DOCTYPE html>\n<html lang=\"en\">\n<body>\n<script type=\"module\">\n\2\n<\/script>\n<\/body>\n<\/html>\n\`\`\`/g"
# Create package.json file for esm branch:
jq --indent 2 '{"name": .name, "version": .version, "description": .description, "license": .license, "type": "module", "main": "./index.mjs", "homepage": .homepage, "repository": .repository, "bugs": .bugs, "keywords": .keywords, "funding": .funding}' package.json > ./esm/package.json
# Delete everything in current directory aside from esm folder:
- name: 'Delete everything in current directory aside from esm folder'
run: |
find . -type 'f' | grep -v -e "esm" -e ".git/" | xargs -r rm
find . -mindepth 1 -type 'd' | grep -v -e "esm" -e ".git" | xargs -r rm -rf
# Move esm directory to root:
- name: 'Move esm directory to root'
run: |
mv ./esm/* .
rmdir ./esm
# Commit changes:
- name: 'Commit changes'
run: |
git add -A
git commit -m "Auto-generated commit"
# Push changes to `esm` branch:
- name: 'Push changes to `esm` branch'
run: |
SLUG=${{ github.repository }}
echo "Pushing changes to $SLUG..."
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" esm
# Send status to Slack channel if job fails:
- name: 'Send status to Slack channel in case of failure'
uses: act10ns/slack@v2
with:
status: ${{ job.status }}
steps: ${{ toJson(steps) }}
channel: '#npm-ci'
if: failure()
# Define job to create CLI branch:
cli:
# Define display name:
name: 'Create CLI branch'
# Define the type of virtual host machine on which to run the job:
runs-on: ubuntu-latest
# Indicate that this job depends on the test job finishing:
needs: test
# Define the sequence of job steps...
steps:
# Checkout the repository:
- name: 'Checkout repository'
uses: actions/checkout@v3
# Configure git:
- name: 'Configure git'
run: |
git config --local user.email "[email protected]"
git config --local user.name "stdlib-bot"
# Check if remote `cli` branch exists:
- name: 'Check if remote `cli` branch exists'
id: cli-branch-exists
continue-on-error: true
run: |
git fetch --all
git ls-remote --exit-code --heads origin cli
if [ $? -eq 0 ]; then
echo "remote-exists=true" >> $GITHUB_OUTPUT
else
echo "remote-exists=false" >> $GITHUB_OUTPUT
fi
# If `cli` exists, delete everything in branch and merge `production` into it
- name: 'If `cli` exists, delete everything in branch and merge `production` into it'
if: steps.cli-branch-exists.outputs.remote-exists
run: |
git checkout -b cli origin/cli
find . -type 'f' | grep -v -e ".git/" -e "package.json" -e "README.md" -e "LICENSE" -e "CONTRIBUTORS" -e "NOTICE" | xargs -r rm
find . -mindepth 1 -type 'd' | grep -v -e ".git" | xargs -r rm -rf
git add -A
git commit -m "Remove files" --allow-empty
git config merge.theirs.name 'simulate `-s theirs`'
git config merge.theirs.driver 'cat %B > %A'
GIT_CONFIG_PARAMETERS="'merge.default=theirs'" git merge origin/production --allow-unrelated-histories
# Copy files from `production` branch if necessary:
git checkout origin/production -- .
if [ -n "$(git status --porcelain)" ]; then
git add -A
git commit -m "Auto-generated commit"
fi
# If `cli` does not exist, create `cli` branch:
- name: 'If `cli` does not exist, create `cli` branch'
if: ${{ steps.cli-branch-exists.outputs.remote-exists == false }}
run: |
git checkout production
git checkout -b cli
# Copy files to cli directory:
- name: 'Copy files to cli directory'
run: |
mkdir -p cli
mkdir -p cli/docs cli/test
cp README.md LICENSE CONTRIBUTORS NOTICE ./cli
cp -r bin etc ./cli
cp test/test.cli.js ./cli/test
if [ -d "test/fixtures" ]; then
cp -r test/fixtures ./cli/test
fi
cp docs/usage.txt ./cli/docs
# Install Node.js:
- name: 'Install Node.js'
uses: actions/setup-node@v3
with:
node-version: 16
timeout-minutes: 5
# Install dependencies:
- name: 'Install production and development dependencies'
id: install
run: |
npm install || npm install || npm install
timeout-minutes: 15
# Rewrite file contents:
- name: 'Rewrite file contents'
run: |
# Define variable for package name:
pkg="$(jq -r '.name' ./package.json)"
escapedPkg=$(echo "$pkg" | sed -e 's/\//\\\//g')
escapedPkg=$(echo "$escapedPkg" | sed -e 's/\@/\\\@/g')
# Define variable for package description:
pkgDescription="$(jq -r '.description' ./package.json)"
pkgDescription="$(echo "$pkgDescription" | sed -e 's/^\([A-Z]\)/\L\1/')"
# Remove sections:
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/<section class=\"installation\">[^<]+<\/section>//;"
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"usage\">[\s\S]+?<\!\-\- \/.usage \-\->//"
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"notes\">[\s\S]+?<\!\-\- \/.notes \-\->//"
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"examples\">[\s\S]+?<\!\-\- \/.examples \-\->//"
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?<section class=\"c\">[\s\S]+?<\!\-\- \/.c \-\->//g"
# Remove first horizontal rule * * *:
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*)//"
# Remove ## CLI heading:
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/## CLI//"
# Change heading levels:
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/###/##/g"
# Append -cli to package name unless it already ends with -cli:
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(?<!\[)($escapedPkg)(?!-cli)/\1-cli/g"
# Insert a link to the main package:
find ./cli -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/<section class=\"related\">(?:\n\n\* \* \*\n\n## See Also\n\n)?/<section class=\"related\">\n\n## See Also\n\n- <span class=\"package-name\">[\`$escapedPkg\`][$escapedPkg]<\/span><span class=\"delimiter\">: <\/span><span class=\"description\">$pkgDescription<\/span>\n/"
# Create package.json file for cli branch:
jq --indent 2 '.name = .name + "-cli" | {"name": .name, "version": .version, "description": .description, "license": .license, "author": .author, "contributors": .contributors, "bin": .bin, "homepage": .homepage, "repository": .repository, "bugs": .bugs, "dependencies": .dependencies, "devDependencies": .devDependencies, "keywords": .keywords, "funding": .funding}' package.json > ./cli/package.json
# Add implementation package as dependency:
version=$(npm view "$pkg" version)
jq --indent 2 ".dependencies[\"$pkg\"] = \"$version\"" ./cli/package.json > ./cli/package.json.tmp
mv ./cli/package.json.tmp ./cli/package.json
# Rewrite require of main module in bin/cli to depend on external package:
perl -0777 -i -pe "s/require\( \'\.\/\.\.\/lib\' \)/require\( \'$escapedPkg\' \)/" ./cli/bin/cli
# For all dependencies, check if they are required by the CLI; if not, remove them:
jq -r '.dependencies | keys[]' ./cli/package.json | while read -r dep; do
dep=$(echo "$dep" | xargs)
if ! grep -q "$dep" ./cli/test/** && ! grep -q "$dep" ./cli/bin/**; then
jq --indent 2 "del(.dependencies[\"$dep\"])" ./cli/package.json > ./cli/package.json.tmp
mv ./cli/package.json.tmp ./cli/package.json
fi
done
jq -r '.devDependencies | keys[]' ./cli/package.json | while read -r dep; do
if [[ "$dep" != "@stdlib"* ]]; then
continue
fi
dep=$(echo "$dep" | xargs)
if ! grep -q "$dep" ./cli/test/** && ! grep -q "$dep" ./cli/bin/**; then
jq --indent 2 "del(.devDependencies[\"$dep\"])" ./cli/package.json > ./cli/package.json.tmp
mv ./cli/package.json.tmp ./cli/package.json
fi
done
# Delete everything in current directory aside from cli folder:
- name: 'Delete everything in current directory aside from cli folder'
run: |
find . -type 'f' | grep -v -e "cli" -e ".git/" | xargs -r rm
find . -mindepth 1 -type 'd' | grep -v -e "cli" -e ".git" | xargs -r rm -rf
# Move cli directory to root:
- name: 'Move cli directory to root'
run: |
mv ./cli/* .
rmdir ./cli
# Commit changes:
- name: 'Commit changes'
run: |
git add -A
git commit -m "Auto-generated commit"
# Push changes to `cli` branch:
- name: 'Push changes to `cli` branch'
run: |
SLUG=${{ github.repository }}
echo "Pushing changes to $SLUG..."
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" cli
# Send status to Slack channel if job fails:
- name: 'Send status to Slack channel in case of failure'
uses: act10ns/slack@v2
with:
status: ${{ job.status }}
steps: ${{ toJson(steps) }}
channel: '#npm-ci'
if: failure()
# Define job that succeeds if all bundles were successfully built:
create-tag-bundles:
# Define display name:
name: 'Create tag bundles'
# Define the type of virtual host machine on which to run the job:
runs-on: ubuntu-latest
# Indicate that this job depends on the bundle jobs finishing:
needs: [ deno, umd, esm, cli ]
# Define the steps to be executed:
steps:
# Checkout the repository:
- name: 'Checkout repository'
uses: actions/checkout@v3
with:
fetch-depth: 2
# Check if workflow run was triggered by a patch, minor, or major version bump:
- name: 'Check if workflow run was triggered by a patch, minor, or major version bump'
id: check-if-bump
continue-on-error: true
run: |
VERSION_CHANGE_PKG_JSON=$(git diff HEAD~1 HEAD package.json | grep '"version":')
if [ -z "$VERSION_CHANGE_PKG_JSON" ]; then
echo "This workflow was not triggered by a version bump."
echo "bump=false" >> $GITHUB_OUTPUT
else
echo "This workflow was triggered by a version bump."
echo "bump=true" >> $GITHUB_OUTPUT
fi
# Configure git:
- name: 'Configure git'
if: steps.check-if-bump.outputs.bump
run: |
git config --local user.email "[email protected]"
git config --local user.name "stdlib-bot"
git fetch --all
# Create bundle tags:
- name: 'Create bundle tags'
if: steps.check-if-bump.outputs.bump
run: |
SLUG=${{ github.repository }}
ESCAPED=$(echo $SLUG | sed -E 's/\//\\\//g')
VERSION="v$(jq --raw-output '.version' package.json)"
git checkout -b deno origin/deno
sed -i -E "s/$ESCAPED@deno/$ESCAPED@$VERSION-deno/g" README.md
git add README.md
git commit -m "Update README.md for Deno bundle $VERSION"
git tag -a $VERSION-deno -m "$VERSION-deno"
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" $VERSION-deno
sed -i -E "s/$ESCAPED@$VERSION-deno/$ESCAPED@deno/g" README.md
perl -0777 -i -pe "s/\`\`\`javascript\nimport\s+([a-zA-Z0-9_]+)\s+from\s*'([^']+)';\n\`\`\`/\`\`\`javascript\nimport \1 from '\2';\n\`\`\`\n\The previous example will load the latest bundled code from the deno branch. Alternatively, you may load a specific version by loading the file from one of the \[tagged bundles\]\(https:\/\/github.com\/$ESCAPED\/tags\). For example,\n\n\`\`\`javascript\nimport \1 from 'https:\/\/cdn\.jsdelivr\.net\/gh\/$ESCAPED\@$VERSION-deno\/mod\.js';\n\`\`\`/" README.md
git add README.md
git commit -m "Auto-generated commit"
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" deno
git checkout -b umd origin/umd
sed -i -E "s/$ESCAPED@umd/$ESCAPED@$VERSION-umd/g" README.md
git add README.md
git commit -m "Update README.md for UMD bundle $VERSION"
git tag -a $VERSION-umd -m "$VERSION-umd"
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" $VERSION-umd
sed -i -E "s/$ESCAPED@$VERSION-umd/$ESCAPED@umd/g" README.md
perl -0777 -i -pe "s/\`\`\`javascript\n([a-zA-Z0-9_]+)\s+=\s*require\(\s*'([^']+)'\s*\)\n\`\`\`/\`\`\`javascript\n\1 = require\( '\2' \)\n\`\`\`\n\The previous example will load the latest bundled code from the umd branch. Alternatively, you may load a specific version by loading the file from one of the \[tagged bundles\]\(https:\/\/github.com\/$ESCAPED\/tags\). For example,\n\n\`\`\`javascript\n\1 = require\( 'https:\/\/cdn\.jsdelivr\.net\/gh\/$ESCAPED\@$VERSION-umd\/browser\.js' \)\n\`\`\`/" README.md
git add README.md
git commit -m "Auto-generated commit"
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" umd
git checkout -b esm origin/esm
sed -i -E "s/$ESCAPED@esm/$ESCAPED@$VERSION-esm/g" README.md
git add README.md
git commit -m "Update README.md for ESM bundle $VERSION"
git tag -a $VERSION-esm -m "$VERSION-esm"
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" $VERSION-esm
sed -i -E "s/$ESCAPED@$VERSION-esm/$ESCAPED@esm/g" README.md
perl -0777 -i -pe "s/\`\`\`javascript\nimport\s+([a-zA-Z0-9_]+)\s+from\s*'([^']+)';\n\`\`\`/\`\`\`javascript\nimport \1 from '\2';\n\`\`\`\n\The previous example will load the latest bundled code from the esm branch. Alternatively, you may load a specific version by loading the file from one of the \[tagged bundles\]\(https:\/\/github.com\/$ESCAPED\/tags\). For example,\n\n\`\`\`javascript\nimport \1 from 'https:\/\/cdn\.jsdelivr\.net\/gh\/$ESCAPED\@$VERSION-esm\/index\.mjs';\n\`\`\`/" README.md
git add README.md
git commit -m "Auto-generated commit"
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" esm
git checkout -b cli origin/cli
sed -i -E "s/$ESCAPED/$ESCAPED@$VERSION/g" README.md
git add README.md
git commit -m "Update README.md for CLI branch $VERSION"
git tag -a $VERSION-cli -m "$VERSION-cli"
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" $VERSION-cli
sed -i -E "s/$ESCAPED@$VERSION/$ESCAPED/g" README.md
git add README.md
git commit -m "Auto-generated commit"
git push "https://$GITHUB_ACTOR:[email protected]/$SLUG.git" cli
# Run publish workflow for CLI package:
- name: 'Run publish workflow for CLI package'
if: steps.check-if-bump.outputs.bump
env:
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: |
gh workflow run publish_cli.yml