Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 10 additions & 102 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,23 @@ inputs:
required: false
default: "false"

outputs:
compact-home:
description: "Path to Compact compiler installation"
value: ${{ steps.compact-outputs.outputs.compact-home }}
compact-version:
description: "Installed Compact compiler version"
value: ${{ steps.compact-outputs.outputs.version }}

runs:
using: "composite"
steps:
- name: Set shared environment variables
shell: bash
run: |
echo "COMPILER_VERSION=0.26.0" >> $GITHUB_ENV
echo "LANGUAGE_VERSION=0.18.0" >> $GITHUB_ENV

- name: Get yarn cache directory path
- name: Enable corepack
shell: bash
run: corepack enable

- name: Cache turbo build setup
uses: actions/cache@v4
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: .turbo
key: ${{ runner.os }}-turbo-${{ hashFiles('.turbo/*') }}-${{ github.sha }}
key: ${{ runner.os }}-turbo-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-${{ hashFiles('.turbo/*') }}

- name: Cache Compact compiler
if: inputs.skip-compact != 'true'
uses: actions/cache@v4
id: compact-cache
with:
path: |
~/.local/bin/compact
key: compact-compiler-${{ env.COMPILER_VERSION }}-${{ runner.os }}
${{ runner.os }}-turbo-

- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version-file: ".nvmrc"
cache: "yarn"
Expand All @@ -62,77 +39,8 @@ runs:
TURBO_TELEMETRY_DISABLED: 1
run: npm install turbo@${{ env.TURBO_MAJOR_VERSION }} -g

- name: Install Compact compiler
if: inputs.skip-compact != 'true' && steps.compact-cache.outputs.cache-hit != 'true'
shell: bash
run: |
set -euo pipefail
COMPACT_HOME="$HOME/.local/bin"
mkdir -p "$COMPACT_HOME"

# Require COMPACT_INSTALLER_URL to be provided by the caller
if [ -z "${COMPACT_INSTALLER_URL:-}" ]; then
echo "::error::COMPACT_INSTALLER_URL is required but not set. Provide it via env or secrets."
exit 1
fi

echo "🔧 Installing Compact compiler from $COMPACT_INSTALLER_URL ..."
curl --proto '=https' --tlsv1.2 -LsSf "$COMPACT_INSTALLER_URL" | sh

echo "🔧 Updating Compact compiler to $COMPILER_VERSION..."
"$COMPACT_HOME/compact" update "$COMPILER_VERSION"

echo "✅ Compact compiler installed"

- name: Setup Compact environment
if: inputs.skip-compact != 'true'
shell: bash
run: |
COMPACT_HOME="$HOME/.local/bin"
echo "📁 Setting Compact environment variables..."
echo "COMPACT_HOME=$COMPACT_HOME" >> "$GITHUB_ENV"
echo "$COMPACT_HOME" >> "$GITHUB_PATH"

if [ -f "$COMPACT_HOME/compact" ]; then
echo "✅ Compact compiler is installed at $COMPACT_HOME"
else
echo "::error::❌ Compact compiler not found in $COMPACT_HOME"
exit 1
fi

- name: Set Compact outputs
if: inputs.skip-compact != 'true'
id: compact-outputs
shell: bash
run: |
echo "compact-home=$HOME/.local/bin" >> $GITHUB_OUTPUT
echo "version=$COMPILER_VERSION" >> $GITHUB_OUTPUT

- name: Check compiler and language version
if: inputs.skip-compact != 'true'
shell: bash
run: |
set -euo pipefail

echo "🔧 Updating Compact compiler to $COMPILER_VERSION..."
"$COMPACT_HOME/compact" update "$COMPILER_VERSION"

echo "🔍 Checking Compact compiler version..."
COMPILER_OUTPUT=$("$COMPACT_HOME/compact" compile --version)
COMPUTED_COMPILER_VERSION=$(echo "$COMPILER_OUTPUT" | grep -oP '\b0\.[0-9]+\.[0-9]+\b' | head -n 1)

if [ "$COMPUTED_COMPILER_VERSION" != "$COMPILER_VERSION" ]; then
echo "::error::❌ Compiler version mismatch!%0AExpected: $COMPILER_VERSION%0AGot: $COMPUTED_COMPILER_VERSION"
exit 1
fi
echo "✅ Compiler version matches: $COMPUTED_COMPILER_VERSION"

echo "🔍 Checking Compact language version..."
LANGUAGE_OUTPUT=$("$COMPACT_HOME/compact" compile --language-version)
COMPUTED_LANGUAGE_VERSION=$(echo "$LANGUAGE_OUTPUT" | grep -oP '\b0\.[0-9]+\.[0-9]+\b' | tail -n 1)

if [ "$COMPUTED_LANGUAGE_VERSION" != "$LANGUAGE_VERSION" ]; then
echo "::error::❌ Language version mismatch!%0AExpected: $LANGUAGE_VERSION%0AGot: $COMPUTED_LANGUAGE_VERSION"
exit 1
fi
echo "✅ Language version matches: $COMPUTED_LANGUAGE_VERSION"
- name: Setup Compact Compiler
if: ${{ inputs.skip-compact != 'true' }}
uses: midnightntwrk/setup-compact-action@4130145456ad3f45934788dd4a65647eb283e658 # loose commit/not released
with:
compact-version: "0.26.0"
14 changes: 8 additions & 6 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
name: Format and Lint

env:
TURBO_TELEMETRY_DISABLED: 1

on:
pull_request:
push:
Expand All @@ -14,12 +11,17 @@ jobs:
name: Run Checks
runs-on: ubuntu-24.04

env:
COMPACT_INSTALLER_URL: ${{ vars.COMPACT_INSTALLER_URL }}
permissions:
contents: read

steps:
- name: Harden Runner
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
with:
egress-policy: audit

- name: Check out code
uses: actions/checkout@v6
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 2 # Recommended by turbo team

Expand Down
88 changes: 88 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Release Package

on:
workflow_dispatch:
inputs:
package:
description: "Which package to release"
required: true
type: choice
options:
- compact-tools-cli
- compact-tools-simulator
version_bump:
description: "Version bump type"
required: true
type: choice
options:
- patch
- minor
- major

jobs:
release:
name: Release ${{ inputs.package }}
runs-on: ubuntu-24.04
environment: compact-npm-prod # Requires approval

permissions:
contents: write # Required to push commits and tags

steps:
- name: Check out code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0

- name: Set package directory
id: pkg
run: |
case "${{ inputs.package }}" in
"compact-tools-cli")
echo "dir=cli" >> $GITHUB_OUTPUT
;;
"compact-tools-simulator")
echo "dir=simulator" >> $GITHUB_OUTPUT
;;
esac

- name: Setup Environment
uses: ./.github/actions/setup

- name: Run tests for package
run: yarn test --filter=@openzeppelin/${{ inputs.package }}

- name: Build package
run: yarn build --filter=@openzeppelin/${{ inputs.package }}

- name: Bump version
id: version
run: |
cd packages/${{ steps.pkg.outputs.dir }}
yarn version ${{ inputs.version_bump }}
NEW_VERSION=$(node -p "require('./package.json').version")
echo "new=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "### Release Summary" >> $GITHUB_STEP_SUMMARY
echo "- Package: ${{ inputs.package }}" >> $GITHUB_STEP_SUMMARY
echo "- New version: $NEW_VERSION" >> $GITHUB_STEP_SUMMARY
echo "- Bump type: ${{ inputs.version_bump }}" >> $GITHUB_STEP_SUMMARY

- name: Verify package contents
run: |
cd packages/${{ steps.pkg.outputs.dir }}
yarn pack --dry-run

- name: Commit and tag version bump
uses: stefanzweifel/git-auto-commit-action@28e16e81777b558cc906c8750092100bbb34c5e3 # v7.0.0
with:
commit_message: "chore: release ${{ inputs.package }} v${{ steps.version.outputs.new }}"
file_pattern: "packages/${{ steps.pkg.outputs.dir }}/package.json"
tagging_message: "${{ inputs.package }}/v${{ steps.version.outputs.new }}"

- name: Publish to npm
run: |
yarn config set npmAuthToken "$NPM_TOKEN"
cd packages/${{ steps.pkg.outputs.dir }}
yarn npm publish --access public --provenance
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
17 changes: 17 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Releasing

1. Go to "Release Package" in Actions.
2. Click on the "Run workflow" dropdown menu.
3. Choose the package to release and the version bump type.
Following [SemVer](https://semver.org/):
- **Patch** - Backward-compatible bug fixes.
- **Minor** - New functionality in a backward compatible way.
- **Major** - Breaking API changes.

4. A maintainer must approve the release before it proceeds.
5. Once approved, the CI will automatically:
- Run tests.
- Bump the version.
- Create a git tag.
- Publish the package to npm.
6. Once published, go to "Releases" and create a GitHub release using the generated tag.
1 change: 0 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"name": "@openzeppelin/compact-tools-cli",
"private": true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we should still remove this. Because I think the name of the package will be a bit misleading, I was thinking to to leave this private and if we are we follow the proposal I had regarding copmact-tools, wdyt?

Copy link
Contributor

@emnul emnul Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's discuss this in a separate PR / Issue to avoid blocking it.

"description": "CLI for compiling and building Compact smart contracts",
"version": "0.0.1",
"keywords": [
Expand Down
1 change: 0 additions & 1 deletion packages/simulator/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"name": "@openzeppelin/compact-tools-simulator",
"private": true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same here, but more specifically for those packages I think its better to remove the -tools- word from the name to be @openzeppelin/compact-simulator wdyt?

"description": "Simulator for testing Compact smart contracts",
"version": "0.0.1",
"keywords": [
Expand Down
40 changes: 38 additions & 2 deletions packages/simulator/test/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Runs once before all tests via Vitest's globalSetup.
*/

import { exec } from 'node:child_process';
import { exec, type SpawnSyncReturns } from 'node:child_process';
import { existsSync, mkdirSync, statSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
Expand All @@ -23,6 +23,27 @@ const CONTRACT_FILES = [
'SampleZOwnable.compact',
];

function isSpawnSyncRet(
err: unknown,
): err is SpawnSyncReturns<string | Buffer> {
if (typeof err !== 'object' || err === null) {
return false;
}

const typedErr = err as Partial<SpawnSyncReturns<string | Buffer>> &
Record<string, unknown>;

const okErr = typedErr.error instanceof Error;
const okStdout =
typeof typedErr.stdout === 'string' || Buffer.isBuffer(typedErr.stdout);
const okStderr =
typeof typedErr.stderr === 'string' || Buffer.isBuffer(typedErr.stderr);
const okStatus =
typeof typedErr.status === 'number' || typedErr.status === null;

return okErr && okStdout && okStderr && okStatus;
}

async function compileContract(contractFile: string): Promise<void> {
const inputPath = join(SAMPLE_CONTRACTS_DIR, contractFile);
const contractName = contractFile.replace('.compact', '');
Expand All @@ -48,7 +69,22 @@ async function compileContract(contractFile: string): Promise<void> {
mkdirSync(join(outputDir, 'keys'), { recursive: true });

const command = `compact compile --skip-zk "${inputPath}" "${outputDir}"`;
await execAsync(command);
try {
await execAsync(command);
} catch (err: unknown) {
if (!isSpawnSyncRet(err)) {
throw err;
}

if (err.status === 127) {
throw new Error(
'`compact` not found (exit code 127). Is it installed and on PATH?',
);
}

throw err;
}

console.log(`✓ Compiled ${contractFile}`);
}

Expand Down