Skip to content

Merge pull request #878 from smucclaw/thomasgorissen/optimizations #99

Merge pull request #878 from smucclaw/thomasgorissen/optimizations

Merge pull request #878 from smucclaw/thomasgorissen/optimizations #99

Workflow file for this run

name: Main Branch Tag
on:
push:
branches: [main]
# Only run one release build at a time
concurrency:
group: main-release
cancel-in-progress: false
env:
GHC_VERSION: "9.10.2"
GHC_WASM_VERSION: "9.10"
jobs:
# ============================================
# Build LSP binaries for each platform
# ============================================
build-lsp-macos-arm64:
name: Build jl4-lsp - macOS ARM64
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Set up GHC
uses: haskell-actions/setup@v2
id: setup
with:
ghc-version: ${{ env.GHC_VERSION }}
cabal-version: "latest"
cabal-update: true
- name: Configure and generate build plan
run: |
cabal update
cabal configure --disable-tests --disable-documentation
cabal build exe:jl4-lsp --dry-run
- name: Restore cached dependencies
uses: actions/cache/restore@v4
id: cache
env:
key: lsp-macos-arm64-ghc-${{ steps.setup.outputs.ghc-version }}-cabal-${{ steps.setup.outputs.cabal-version }}
with:
path: ${{ steps.setup.outputs.cabal-store }}
key: ${{ env.key }}-plan-${{ hashFiles('**/plan.json') }}
restore-keys: ${{ env.key }}-
- name: Install dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: cabal build exe:jl4-lsp --only-dependencies
- name: Save cached dependencies
uses: actions/cache/save@v4
if: steps.cache.outputs.cache-hit != 'true'
with:
path: ${{ steps.setup.outputs.cabal-store }}
key: ${{ steps.cache.outputs.cache-primary-key }}
- name: Build jl4-lsp
run: cabal build exe:jl4-lsp
- name: Copy and process binary
run: |
mkdir -p bin/darwin-arm64
cp $(cabal list-bin exe:jl4-lsp) bin/darwin-arm64/jl4-lsp
strip bin/darwin-arm64/jl4-lsp || true
codesign -s - bin/darwin-arm64/jl4-lsp || true
chmod +x bin/darwin-arm64/jl4-lsp
ls -lh bin/darwin-arm64/
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: jl4-lsp-darwin-arm64
path: bin/darwin-arm64/jl4-lsp
retention-days: 90
build-lsp-windows:
name: Build jl4-lsp + jl4-cli - Windows x64
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Set up GHC
uses: haskell-actions/setup@v2
id: setup
with:
ghc-version: ${{ env.GHC_VERSION }}
cabal-version: "latest"
cabal-update: true
- name: Configure and build
shell: bash
run: |
cabal update
cabal configure --disable-tests --disable-documentation
cabal build exe:jl4-lsp exe:jl4-cli --dry-run
- name: Restore cached dependencies
uses: actions/cache/restore@v4
id: cache
env:
key: lsp-windows-x64-ghc-${{ steps.setup.outputs.ghc-version }}-cabal-${{ steps.setup.outputs.cabal-version }}
with:
path: ${{ steps.setup.outputs.cabal-store }}
key: ${{ env.key }}-plan-${{ hashFiles('**/plan.json') }}
restore-keys: ${{ env.key }}-
- name: Install dependencies
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
run: cabal build exe:jl4-lsp exe:jl4-cli --only-dependencies
- name: Save cached dependencies
uses: actions/cache/save@v4
if: steps.cache.outputs.cache-hit != 'true'
with:
path: ${{ steps.setup.outputs.cabal-store }}
key: ${{ steps.cache.outputs.cache-primary-key }}
- name: Build jl4-lsp and jl4-cli
shell: bash
run: cabal build exe:jl4-lsp exe:jl4-cli
- name: Copy binaries
shell: bash
run: |
mkdir -p bin/win32-x64
cp $(cabal list-bin exe:jl4-lsp) bin/win32-x64/jl4-lsp.exe
cp $(cabal list-bin exe:jl4-cli) bin/win32-x64/jl4-cli.exe
ls -lh bin/win32-x64/
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: jl4-lsp-win32-x64
path: bin/win32-x64/
retention-days: 90
build-lsp-linux-x64:
name: Build jl4-lsp + jl4-service - Linux x64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install system dependencies
run: |
for i in 1 2 3; do
sudo apt-get update && break
echo "Retry $i: apt-get update failed, waiting 10s..."
sleep 10
done
sudo apt-get install -y pkg-config liblzma-dev libgmp-dev
- name: Set up GHC
uses: haskell-actions/setup@v2
id: setup
with:
ghc-version: ${{ env.GHC_VERSION }}
cabal-version: "latest"
cabal-update: true
- name: Configure and build
run: |
cabal update
cabal configure --disable-tests --disable-documentation
cabal build exe:jl4-lsp exe:jl4-service --dry-run
- name: Restore cached dependencies
uses: actions/cache/restore@v4
id: cache
env:
key: lsp-linux-x64-ghc-${{ steps.setup.outputs.ghc-version }}-cabal-${{ steps.setup.outputs.cabal-version }}
with:
path: ${{ steps.setup.outputs.cabal-store }}
key: ${{ env.key }}-plan-${{ hashFiles('**/plan.json') }}
restore-keys: ${{ env.key }}-
- name: Install dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: cabal build exe:jl4-lsp exe:jl4-service --only-dependencies
- name: Save cached dependencies
uses: actions/cache/save@v4
if: steps.cache.outputs.cache-hit != 'true'
with:
path: ${{ steps.setup.outputs.cabal-store }}
key: ${{ steps.cache.outputs.cache-primary-key }}
- name: Build jl4-lsp and jl4-service
run: cabal build exe:jl4-lsp exe:jl4-service
- name: Copy and process binaries
run: |
mkdir -p bin/linux-x64
cp $(cabal list-bin exe:jl4-lsp) bin/linux-x64/jl4-lsp
strip bin/linux-x64/jl4-lsp || true
chmod +x bin/linux-x64/jl4-lsp
cp $(cabal list-bin exe:jl4-service) bin/linux-x64/jl4-service
strip bin/linux-x64/jl4-service || true
chmod +x bin/linux-x64/jl4-service
# Generate SHA256 for jl4-service
sha256sum bin/linux-x64/jl4-service | awk '{print $1}' > bin/linux-x64/jl4-service.sha256
echo "jl4-service SHA256: $(cat bin/linux-x64/jl4-service.sha256)"
ls -lh bin/linux-x64/
- name: Upload LSP binary artifact
uses: actions/upload-artifact@v4
with:
name: jl4-lsp-linux-x64
path: bin/linux-x64/jl4-lsp
retention-days: 90
- name: Upload jl4-service artifact
uses: actions/upload-artifact@v4
with:
name: jl4-service-linux-x64
path: |
bin/linux-x64/jl4-service
bin/linux-x64/jl4-service.sha256
retention-days: 90
build-lsp-linux-arm64:
name: Build jl4-lsp - Linux ARM64
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install system dependencies
run: |
for i in 1 2 3; do
sudo apt-get update && break
echo "Retry $i: apt-get update failed, waiting 10s..."
sleep 10
done
sudo apt-get install -y pkg-config liblzma-dev libgmp-dev
- name: Set up GHC
uses: haskell-actions/setup@v2
id: setup
with:
ghc-version: ${{ env.GHC_VERSION }}
cabal-version: "latest"
cabal-update: true
- name: Configure and build
run: |
cabal update
cabal configure --disable-tests --disable-documentation
cabal build exe:jl4-lsp --dry-run
- name: Restore cached dependencies
uses: actions/cache/restore@v4
id: cache
env:
key: lsp-linux-arm64-ghc-${{ steps.setup.outputs.ghc-version }}-cabal-${{ steps.setup.outputs.cabal-version }}
with:
path: ${{ steps.setup.outputs.cabal-store }}
key: ${{ env.key }}-plan-${{ hashFiles('**/plan.json') }}
restore-keys: ${{ env.key }}-
- name: Install dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: cabal build exe:jl4-lsp --only-dependencies
- name: Save cached dependencies
uses: actions/cache/save@v4
if: steps.cache.outputs.cache-hit != 'true'
with:
path: ${{ steps.setup.outputs.cabal-store }}
key: ${{ steps.cache.outputs.cache-primary-key }}
- name: Build jl4-lsp
run: cabal build exe:jl4-lsp
- name: Copy and process binary
run: |
mkdir -p bin/linux-arm64
cp $(cabal list-bin exe:jl4-lsp) bin/linux-arm64/jl4-lsp
strip bin/linux-arm64/jl4-lsp || true
chmod +x bin/linux-arm64/jl4-lsp
ls -lh bin/linux-arm64/
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: jl4-lsp-linux-arm64
path: bin/linux-arm64/jl4-lsp
retention-days: 90
# ============================================
# Build WASM
# ============================================
build-wasm:
name: Build WASM
runs-on: ubuntu-latest
outputs:
version: ${{ steps.prepare-artifacts.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: true
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y curl xz-utils binaryen
- name: Cache GHC WASM toolchain
id: cache-ghc-wasm
uses: actions/cache@v4
with:
path: ~/.ghc-wasm
key: ghc-wasm-${{ env.GHC_WASM_VERSION }}-${{ runner.os }}
- name: Install GHC WASM toolchain
if: steps.cache-ghc-wasm.outputs.cache-hit != 'true'
run: |
curl -L https://gitlab.haskell.org/haskell-wasm/ghc-wasm-meta/-/raw/master/bootstrap.sh | FLAVOUR=${{ env.GHC_WASM_VERSION }} bash
shell: bash
- name: Cache WASM dependencies
uses: actions/cache@v4
with:
path: |
~/.ghc-wasm/.cabal/store
dist-newstyle
key: wasm-deps-${{ env.GHC_WASM_VERSION }}-${{ hashFiles('cabal-wasm.project', 'jl4-core/jl4-core.cabal', 'jl4-wasm/jl4-wasm.cabal') }}
restore-keys: |
wasm-deps-${{ env.GHC_WASM_VERSION }}-
- name: Build WASM binary
run: |
source ~/.ghc-wasm/env
wasm32-wasi-cabal update
wasm32-wasi-cabal build jl4-wasm --project-file=cabal-wasm.project
- name: Generate JS FFI glue code
run: |
source ~/.ghc-wasm/env
WASM_PATH=$(find dist-newstyle -name 'jl4-wasm.wasm' -path '*/opt/build/*' | head -1)
$(wasm32-wasi-ghc --print-libdir)/post-link.mjs -i "$WASM_PATH" -o dist-newstyle/jl4-wasm.mjs
- name: Optimize WASM binary
run: |
WASM_PATH=$(find dist-newstyle -name 'jl4-wasm.wasm' -path '*/opt/build/*' | head -1)
wasm-opt -Oz "$WASM_PATH" -o "$WASM_PATH.opt"
mv "$WASM_PATH.opt" "$WASM_PATH"
- name: Prepare artifacts
id: prepare-artifacts
run: |
mkdir -p wasm-artifacts
WASM_PATH=$(find dist-newstyle -name 'jl4-wasm.wasm' -path '*/opt/build/*' | head -1)
cp "$WASM_PATH" wasm-artifacts/jl4-core.wasm
cp dist-newstyle/jl4-wasm.mjs wasm-artifacts/jl4-core.mjs
COMMIT_SHA="${{ github.sha }}"
SHORT_SHA="${COMMIT_SHA:0:8}"
DATE=$(date -u +%Y%m%d)
VERSION="${DATE}-${SHORT_SHA}"
echo "$VERSION" > wasm-artifacts/version.txt
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Upload WASM artifacts
uses: actions/upload-artifact@v4
with:
name: jl4-wasm-${{ steps.prepare-artifacts.outputs.version }}
path: wasm-artifacts/
retention-days: 90
# ============================================
# Package platform-specific VSCode extensions
# ============================================
package-vscode-extension:
name: Package VSCode Extension - ${{ matrix.target }}
runs-on: ubuntu-latest
needs:
- build-lsp-macos-arm64
- build-lsp-windows
- build-lsp-linux-x64
- build-lsp-linux-arm64
strategy:
fail-fast: false
matrix:
include:
- target: darwin-arm64
artifact: jl4-lsp-darwin-arm64
binary: jl4-lsp
- target: win32-x64
artifact: jl4-lsp-win32-x64
binary: jl4-lsp.exe
- target: linux-x64
artifact: jl4-lsp-linux-x64
binary: jl4-lsp
- target: linux-arm64
artifact: jl4-lsp-linux-arm64
binary: jl4-lsp
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20.x"
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci
- name: Update package.json version with build number
working-directory: ts-apps/vscode
run: |
CURRENT_VERSION=$(node -p "require('./package.json').version")
MAJOR_MINOR=$(echo $CURRENT_VERSION | sed 's/\.[^.]*$//')
NEW_VERSION="${MAJOR_MINOR}.${{ github.run_number }}"
echo "Updating version: $CURRENT_VERSION -> $NEW_VERSION"
node -e "const fs = require('fs'); const pkg = JSON.parse(fs.readFileSync('package.json')); pkg.version = '$NEW_VERSION'; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');"
echo "PACKAGE_VERSION=$NEW_VERSION" >> $GITHUB_ENV
- name: Build TypeScript monorepo
run: npm run build
- name: Download LSP binary
uses: actions/download-artifact@v4
with:
name: ${{ matrix.artifact }}
path: ts-apps/vscode/bin/${{ matrix.target }}
- name: Make binary executable
if: matrix.target != 'win32-x64'
run: chmod +x ts-apps/vscode/bin/${{ matrix.target }}/${{ matrix.binary }}
- name: Copy L4 libraries
run: |
mkdir -p ts-apps/vscode/libraries
cp jl4-core/libraries/*.l4 ts-apps/vscode/libraries/
- name: Package platform-specific extension
working-directory: ts-apps/vscode
run: |
npx vsce package --target ${{ matrix.target }} --no-dependencies -o l4-vscode-${{ matrix.target }}-${{ env.PACKAGE_VERSION }}.vsix
- name: Upload VSIX artifact
uses: actions/upload-artifact@v4
with:
name: l4-vscode-${{ matrix.target }}-${{ env.PACKAGE_VERSION }}
path: ts-apps/vscode/*.vsix
retention-days: 90
# ============================================
# Package all-platforms extension
# ============================================
package-vscode-all-platforms:
name: Package VSCode Extension - All Platforms
runs-on: ubuntu-latest
needs:
- build-lsp-macos-arm64
- build-lsp-windows
- build-lsp-linux-x64
- build-lsp-linux-arm64
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20.x"
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci
- name: Update package.json version with build number
working-directory: ts-apps/vscode
run: |
CURRENT_VERSION=$(node -p "require('./package.json').version")
MAJOR_MINOR=$(echo $CURRENT_VERSION | sed 's/\.[^.]*$//')
NEW_VERSION="${MAJOR_MINOR}.${{ github.run_number }}"
node -e "const fs = require('fs'); const pkg = JSON.parse(fs.readFileSync('package.json')); pkg.version = '$NEW_VERSION'; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');"
echo "PACKAGE_VERSION=$NEW_VERSION" >> $GITHUB_ENV
- name: Build TypeScript monorepo
run: npm run build
- name: Download all LSP binaries
uses: actions/download-artifact@v4
with:
pattern: jl4-lsp-*
path: ts-apps/vscode/bin
- name: Organize binaries into correct structure
run: |
cd ts-apps/vscode/bin
mv jl4-lsp-darwin-arm64 darwin-arm64
mv jl4-lsp-win32-x64 win32-x64
mv jl4-lsp-linux-x64 linux-x64
mv jl4-lsp-linux-arm64 linux-arm64
chmod +x darwin-arm64/jl4-lsp
chmod +x linux-x64/jl4-lsp
chmod +x linux-arm64/jl4-lsp
- name: Copy L4 libraries
run: |
mkdir -p ts-apps/vscode/libraries
cp jl4-core/libraries/*.l4 ts-apps/vscode/libraries/
- name: Package all-platforms extension
working-directory: ts-apps/vscode
run: |
npx vsce package --no-dependencies -o l4-vscode-all-platforms-${{ env.PACKAGE_VERSION }}.vsix
- name: Upload VSIX artifact
uses: actions/upload-artifact@v4
with:
name: l4-vscode-all-platforms-${{ env.PACKAGE_VERSION }}
path: ts-apps/vscode/*.vsix
retention-days: 90
# ============================================
# Package universal extension (no bundled binary)
# ============================================
package-vscode-universal:
name: Package VSCode Extension - Universal
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20.x"
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci
- name: Update package.json version with build number
working-directory: ts-apps/vscode
run: |
CURRENT_VERSION=$(node -p "require('./package.json').version")
MAJOR_MINOR=$(echo $CURRENT_VERSION | sed 's/\.[^.]*$//')
NEW_VERSION="${MAJOR_MINOR}.${{ github.run_number }}"
node -e "const fs = require('fs'); const pkg = JSON.parse(fs.readFileSync('package.json')); pkg.version = '$NEW_VERSION'; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');"
echo "PACKAGE_VERSION=$NEW_VERSION" >> $GITHUB_ENV
- name: Build TypeScript monorepo
run: npm run build
- name: Package universal extension
working-directory: ts-apps/vscode
run: |
npx vsce package --no-dependencies -o l4-vscode-universal-${{ env.PACKAGE_VERSION }}.vsix
- name: Upload VSIX artifact
uses: actions/upload-artifact@v4
with:
name: l4-vscode-universal-${{ env.PACKAGE_VERSION }}
path: ts-apps/vscode/*.vsix
retention-days: 90
# ============================================
# Create Git Tag with Artifacts
# ============================================
create-tag:
name: Create Git Tag
runs-on: ubuntu-latest
needs:
- package-vscode-extension
- package-vscode-all-platforms
- package-vscode-universal
- build-wasm
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Organize artifacts for tag
run: |
mkdir -p release-artifacts
echo "Downloaded artifacts structure:"
find artifacts -type f
# Collect VSIX files
find artifacts -name "*.vsix" -exec cp {} release-artifacts/ \;
# Collect WASM files
find artifacts -name "jl4-core.wasm" -exec cp {} release-artifacts/ \;
find artifacts -name "jl4-core.mjs" -exec cp {} release-artifacts/ \;
find artifacts -name "version.txt" -exec cp {} release-artifacts/wasm-version.txt \; 2>/dev/null || true
# Collect jl4-service binary and SHA256
if [ -d artifacts/jl4-service-linux-x64 ]; then
cp artifacts/jl4-service-linux-x64/jl4-service release-artifacts/jl4-service-linux-x64
cp artifacts/jl4-service-linux-x64/jl4-service.sha256 release-artifacts/jl4-service-linux-x64.sha256
echo "jl4-service SHA256: $(cat release-artifacts/jl4-service-linux-x64.sha256)"
fi
echo "Release artifacts:"
ls -la release-artifacts/
# Fail if no artifacts found
if [ -z "$(ls -A release-artifacts/)" ]; then
echo "ERROR: No artifacts found!"
exit 1
fi
- name: Get build date
id: build-date
run: |
echo "date=$(date -u '+%Y-%m-%d')" >> $GITHUB_OUTPUT
echo "datetime=$(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_OUTPUT
- name: Create tag name
id: tag-name
run: |
TAG_NAME="vscode-wasm-build-${{ github.run_number }}"
echo "tag=$TAG_NAME" >> $GITHUB_OUTPUT
- name: Create Git Tag
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "${{ steps.tag-name.outputs.tag }}" -m "Automated build ${{ github.run_number }}
Commit: ${{ github.sha }}
Built: ${{ steps.build-date.outputs.datetime }}
Artifacts included:
- VSCode extensions (platform-specific, all-platforms, universal)
- WASM binaries (jl4-core.wasm, jl4-core.mjs)
- jl4-service binary (linux-x64) with SHA256"
git push origin "${{ steps.tag-name.outputs.tag }}"
- name: Upload artifacts to tag
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.tag-name.outputs.tag }}
name: L4 VSCode Extension & WASM (Build ${{ github.run_number }})
body: |
## Build Artifacts
**Commit:** ${{ github.sha }}
**Built:** ${{ steps.build-date.outputs.datetime }}
### VSCode Extensions
| Platform | Description |
|----------|-------------|
| `darwin-arm64` | macOS Apple Silicon (also works on Intel via Rosetta 2) |
| `win32-x64` | Windows x64 |
| `linux-x64` | Linux x64 |
| `linux-arm64` | Linux ARM64 |
| `all-platforms` | Single VSIX with all platform binaries |
| `universal` | No bundled binary (requires jl4-lsp on PATH) |
### jl4-service (Decision Service)
| File | Description |
|------|-------------|
| `jl4-service-linux-x64` | Decision service binary for Linux x86_64 |
| `jl4-service-linux-x64.sha256` | SHA256 hash for binary verification |
### WASM Binaries
| File | Description |
|------|-------------|
| `jl4-core.wasm` | L4 core WASM module |
| `jl4-core.mjs` | JavaScript FFI glue code |
### Installation
**VSCode Extension:**
```bash
code --install-extension l4-vscode-<platform>-*.vsix
```
**macOS Security Note:**
```bash
xattr -dr com.apple.quarantine ~/.vscode/extensions/legalese.l4-vscode-*/bin/darwin-*/jl4-lsp
```
files: |
release-artifacts/*
draft: false
prerelease: false
make_latest: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ============================================
# Build summary
# ============================================
build-summary:
name: Build Summary
runs-on: ubuntu-latest
needs:
- package-vscode-extension
- package-vscode-all-platforms
- package-vscode-universal
- build-wasm
- create-tag
if: always()
steps:
- name: Summary
run: |
echo "## Main Branch Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Build Number:** ${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY
echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Build Status" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Component | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-----------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| VSCode Extensions | ${{ needs.package-vscode-extension.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY
echo "| All Platforms | ${{ needs.package-vscode-all-platforms.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY
echo "| Universal | ${{ needs.package-vscode-universal.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY
echo "| WASM Build | ${{ needs.build-wasm.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY
echo "| Git Tag | ${{ needs.create-tag.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY