Skip to content

perf: prepare oracle quote contexts concurrently (#2826) #931

perf: prepare oracle quote contexts concurrently (#2826)

perf: prepare oracle quote contexts concurrently (#2826) #931

name: NPM Packages Release
on:
push:
branches:
- main
jobs:
release:
# skip this job if the commit was created by this workflow (prevents infinite loop)
if: ${{ github.ref == 'refs/heads/main' && !startsWith(github.event.head_commit.message, 'NPM Package Release') }}
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
env:
DEPLOYMENT_KEY: ${{ secrets.PRIVATE_KEY }}
CI_FORK_SEPOLIA_BLOCK_NUMBER: ${{ vars.CI_FORK_SEPOLIA_BLOCK_NUMBER }}
CI_FORK_SEPOLIA_DEPLOYER_ADDRESS: ${{ vars.CI_FORK_SEPOLIA_DEPLOYER_ADDRESS }}
CI_DEPLOY_SEPOLIA_RPC_URL: ${{ secrets.CI_DEPLOY_SEPOLIA_RPC_URL || vars.CI_DEPLOY_SEPOLIA_RPC_URL }}
CI_SEPOLIA_METABOARD_URL: ${{ vars.CI_SEPOLIA_METABOARD_URL }}
CI_DEPLOY_ARBITRUM_RPC_URL: ${{ secrets.CI_DEPLOY_ARBITRUM_RPC_URL }}
CI_DEPLOY_BASE_RPC_URL: ${{ secrets.CI_DEPLOY_BASE_RPC_URL }}
CI_DEPLOY_BASE_SEPOLIA_RPC_URL: ${{ secrets.CI_DEPLOY_BASE_SEPOLIA_RPC_URL }}
CI_DEPLOY_POLYGON_RPC_URL: ${{ secrets.CI_DEPLOY_POLYGON_RPC_URL }}
CI_DEPLOY_FLARE_RPC_URL: ${{ secrets.CI_DEPLOY_FLARE_RPC_URL }}
RPC_URL_ETHEREUM_FORK: ${{ secrets.RPC_URL_ETHEREUM_FORK }}
COMMIT_SHA: ${{ github.sha }}
outputs:
version: ${{ env.NEW_VERSION }}
steps:
# checkout with SSH key to allow pushing version bump commits back to repo
- uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.PUBLISH_PRIVATE_KEY }}
# WASM builds require significant disk space; free up space to prevent build failures
- name: Free disk space
uses: jlumbroso/free-disk-space@v1.3.1
with:
swap-storage: false
# install nix for building WASM artifacts and running tests
- uses: nixbuild/nix-quick-install-action@v30
with:
nix_conf: |
keep-env-derivations = true
keep-outputs = true
# pull rainix derivations from shared Cachix; push new ones if the
# token is set. continue-on-error so a token miss / Cachix outage
# degrades gracefully.
- uses: cachix/cachix-action@v15
continue-on-error: true
with:
name: rainlanguage
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
useDaemon: false
- name: Restore and save Nix store
uses: nix-community/cache-nix-action@v7
with:
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
restore-prefixes-first-match: nix-${{ runner.os }}-
gc-max-store-size-linux: 8G
- uses: Swatinem/rust-cache@v2
with:
prefix-key: rust-${{ github.workflow }}
- name: Cache npm
uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ github.workflow }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: npm-${{ runner.os }}-
# setup node with npm registry for OIDC-based publishing (no NPM_TOKEN needed)
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "24.x"
registry-url: "https://registry.npmjs.org"
# npm 10.9+ required for OIDC provenance support
- name: Upgrade npm for OIDC
run: |
npm install -g npm@latest
npm --version
# ensure GitHub Actions OIDC token is available for npm provenance attestation
- name: Verify OIDC availability
run: |
if [ -n "${ACTIONS_ID_TOKEN_REQUEST_URL}" ] && [ -n "${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" ]; then
echo "OIDC token available"
echo "Endpoint: ${ACTIONS_ID_TOKEN_REQUEST_URL}"
else
echo "OIDC token NOT available"
echo "Check workflow permissions include 'id-token: write'"
exit 1
fi
# npm OIDC publish requires package.json repository URL to match git remote
# mismatch causes 422 error during publish
- name: Verify repository configuration
run: |
echo "Checking repository consistency..."
GIT_REPO=$(git remote get-url origin | sed 's/.*github.com[/:]//; s/.git$//')
DEX_PKG_REPO=$(node -e "console.log(require('./packages/raindex/package.json').repository?.url || '')" | sed 's|https://github.com/||; s|git+||; s|.git$||')
UC_PKG_REPO=$(node -e "console.log(require('./packages/ui-components/package.json').repository?.url || '')" | sed 's|https://github.com/||; s|git+||; s|.git$||')
echo "Git remote: $GIT_REPO"
echo "raindex package.json: $DEX_PKG_REPO"
echo "ui-components package.json: $UC_PKG_REPO"
if [ "$GIT_REPO" != "$DEX_PKG_REPO" ]; then
echo "Repository mismatch for raindex!"
echo "This will cause 422 error during publish"
exit 1
fi
if [ "$GIT_REPO" != "$UC_PKG_REPO" ]; then
echo "Repository mismatch for ui-components!"
echo "This will cause 422 error during publish"
exit 1
fi
echo "Repositories match"
# forge install + build is no longer needed here — all sol! macros
# read committed ABIs under crates/*/abis/, and the wasm + npm builds
# below don't shell out to forge. The prior "Remove Unused Artifacts"
# / debug-dir scrubs went with forge; rust-cache + free-disk-space@v1
# handle disk budget for the remaining WASM builds.
# WASM linker can run out of memory on GitHub runners; add swap to prevent OOM
- name: Add swap space
run: |
if [ -f /swapfile ]; then
sudo swapoff /swapfile 2>/dev/null || true
sudo rm -f /swapfile
fi
sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# build and test WASM bindings
- name: Test JS/TS Binding 1/2
run: |
nix develop .#wasm-shell -c bash -c "CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner cargo test --target wasm32-unknown-unknown --lib -p raindex_quote -p raindex_bindings -p raindex_js_api -p raindex_common"
# run JS/TS integration tests against WASM bindings
- name: Test JS/TS Binding 2/2
run: |
nix develop .#wasm-shell -c bash -c '
set -euxo pipefail
npm install --no-check
cd packages/raindex
npm run build
npm test
'
# build and test UI components before publishing
- name: Build UI Components
run: nix develop .#wasm-shell -c npm run build -w @rainlanguage/ui-components
- name: Test UI Components
run: nix develop .#wasm-shell -c npm run test -w @rainlanguage/ui-components
# check for npm package blacklists pkgs across all raindex related packages
- uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main
- uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main
with:
working-directory: packages/raindex
- uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main
with:
working-directory: packages/ui-components
# configure git identity for version bump commits
- name: Git Config
run: |
git config --global user.email "${{ secrets.CI_GIT_EMAIL }}"
git config --global user.name "${{ secrets.CI_GIT_USER }}"
# get hash of latest published pkgs from npm and concat them
- name: Get Old Hash
run: |
DEX_PKG_OLD_HASH=$(npm view @rainlanguage/raindex@latest dist.shasum 2>/dev/null || echo "none")
UC_PKG_OLD_HASH=$(npm view @rainlanguage/ui-components@latest dist.shasum 2>/dev/null || echo "none")
OLD_HASH=$DEX_PKG_OLD_HASH-$UC_PKG_OLD_HASH
echo "OLD_HASH=$OLD_HASH" >> $GITHUB_ENV
echo "old hash: $OLD_HASH"
# calc hash of current workspace pkgs by packing them and concat them
- name: Get New Hash
run: |
DEX_PKG_NEW_HASH=$(npm pack --silent -w @rainlanguage/raindex | xargs shasum | cut -c1-40)
UC_PKG_NEW_HASH=$(npm pack --silent -w @rainlanguage/ui-components | xargs shasum | cut -c1-40)
NEW_HASH=$DEX_PKG_NEW_HASH-$UC_PKG_NEW_HASH
echo "NEW_HASH=$NEW_HASH" >> $GITHUB_ENV
echo "new hash: $NEW_HASH"
rm -f *.tgz
# from here on, we'll skip if OLD_HASH and NEW_HASH are the same (ie no publish)
# this means we need to skip every step by using an if statement.
# set npm package versions independently
- name: Set Version
if: ${{ env.OLD_HASH != env.NEW_HASH }}
run: |
# npm version prerelease reifies the workspace, which resolves
# @rainlanguage/raindex against the registry. The first time the
# package is published it doesn't exist there yet, so that resolution
# 404s and the bump fails (E404). When npm view reports no published
# version, publish the version already committed in package.json as
# the initial release instead of bumping it.
if npm view @rainlanguage/raindex@latest version &>/dev/null; then
npm version prerelease --preid alpha --no-git-tag-version -w @rainlanguage/raindex
echo "FIRST_PUBLISH=false" >> $GITHUB_ENV
else
echo "@rainlanguage/raindex not yet on npm; publishing committed version as initial release"
echo "FIRST_PUBLISH=true" >> $GITHUB_ENV
fi
RAINDEX_NEW_VERSION=$(jq -r '.version' ./packages/raindex/package.json)
echo "RAINDEX_NEW_VERSION=$RAINDEX_NEW_VERSION" >> $GITHUB_ENV
jq --arg v "$RAINDEX_NEW_VERSION" '.dependencies."@rainlanguage/raindex" = $v' ./packages/ui-components/package.json > tmp.json && mv tmp.json ./packages/ui-components/package.json
npx prettier --write ./packages/ui-components/package.json
npm version prerelease --preid alpha --no-git-tag-version -w @rainlanguage/ui-components
UC_NEW_VERSION=$(jq -r '.version' ./packages/ui-components/package.json)
echo "UC_NEW_VERSION=$UC_NEW_VERSION" >> $GITHUB_ENV
jq --indent 4 --arg rd "$RAINDEX_NEW_VERSION" --arg uc "$UC_NEW_VERSION" '
.packages."packages/raindex".version = $rd |
.packages."packages/ui-components".version = $uc |
.packages."packages/ui-components".dependencies."@rainlanguage/raindex" = $rd
' ./package-lock.json > tmp.json && mv tmp.json ./package-lock.json
# Create raindex npm package tarball
- name: Create raindex NPM Package Tarball
if: ${{ env.OLD_HASH != env.NEW_HASH }}
run: echo "RAINDEX_NPM_PACKAGE=$(npm pack --silent -w @rainlanguage/raindex)" >> $GITHUB_ENV
- name: Rename raindex NPM Package Tarball
if: ${{ env.OLD_HASH != env.NEW_HASH }}
run: mv ${{ env.RAINDEX_NPM_PACKAGE }} raindex_npm_package_${{ env.RAINDEX_NEW_VERSION }}.tgz
# first publish raindex pkg to npm (uses NPM_TOKEN)
- name: First Publish raindex pkg To NPM
if: ${{ env.OLD_HASH != env.NEW_HASH && env.FIRST_PUBLISH == 'true' }}
uses: JS-DevTools/npm-publish@v3
with:
token: ${{ secrets.NPM_TOKEN }}
access: public
package: raindex_npm_package_${{ env.RAINDEX_NEW_VERSION }}.tgz
tag: latest
# publish raindex pkg to npm
- name: Publish raindex pkg To NPM
if: ${{ env.OLD_HASH != env.NEW_HASH && env.FIRST_PUBLISH == 'false' }}
run: |
npm publish raindex_npm_package_${{ env.RAINDEX_NEW_VERSION }}.tgz \
--access public \
--tag latest \
--verbose
# Create npm package tarball for ui-components
- name: Create ui-components NPM Package Tarball
if: ${{ env.OLD_HASH != env.NEW_HASH }}
run: echo "UC_NPM_PACKAGE=$(npm pack --silent -w @rainlanguage/ui-components)" >> $GITHUB_ENV
- name: Rename ui-components NPM Package Tarball
if: ${{ env.OLD_HASH != env.NEW_HASH }}
run: mv ${{ env.UC_NPM_PACKAGE }} ui_components_npm_package_${{ env.UC_NEW_VERSION }}.tgz
# publish ui-components to npm
- name: Publish ui-components To NPM
if: ${{ env.OLD_HASH != env.NEW_HASH }}
run: |
npm publish ui_components_npm_package_${{ env.UC_NEW_VERSION }}.tgz \
--access public \
--tag latest \
--verbose
# Commit changes and tag
- name: Commit And Tag
if: ${{ env.OLD_HASH != env.NEW_HASH }}
run: |
git add "packages/raindex/package.json"
git add "packages/ui-components/package.json"
git add "package-lock.json"
git commit -m "NPM Package Release raindex v${{ env.RAINDEX_NEW_VERSION }} ui-components v${{ env.UC_NEW_VERSION }}"
git tag "npm-raindex-v${{ env.RAINDEX_NEW_VERSION }}-uc-v${{ env.UC_NEW_VERSION }}"
# Push the commit to remote
- name: Push Changes To Remote
if: ${{ env.OLD_HASH != env.NEW_HASH }}
run: |
git push origin
git push -u origin "npm-raindex-v${{ env.RAINDEX_NEW_VERSION }}-uc-v${{ env.UC_NEW_VERSION }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Create gitHub release with tarballs
- name: Create GitHub Release
if: ${{ env.OLD_HASH != env.NEW_HASH }}
id: gh_release
uses: softprops/action-gh-release@v2
with:
tag_name: npm-raindex-v${{ env.RAINDEX_NEW_VERSION }}-uc-v${{ env.UC_NEW_VERSION }}
name: NPM Package Release raindex v${{ env.RAINDEX_NEW_VERSION }} ui-components v${{ env.UC_NEW_VERSION }}
files: |
raindex_npm_package_${{ env.RAINDEX_NEW_VERSION }}.tgz
ui_components_npm_package_${{ env.UC_NEW_VERSION }}.tgz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# forwards status to telegram chat if this ci fails or gets canceled, only runs for default branch
- name: Forward CI Status
if: always()
uses: rainlanguage/github-chore/.github/actions/telegram-status-report@main
with:
status: ${{ job.status }}
telegram-bot-token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
telegram-chat-id: ${{ secrets.TELEGRAM_CHAT_ID }}