Skip to content
Merged
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
275 changes: 32 additions & 243 deletions .github/workflows/contract-release.yml
Original file line number Diff line number Diff line change
@@ -1,250 +1,39 @@
name: Build and Release Contract
name: Build Wasm, add versioned .wasm on GH, add attestation to Stellar.Expert

on:
workflow_call:
inputs:
profile:
description: "Cargo profile to build the contract under. Default release"
type: string
required: false
relative_path:
description: "Relative path to the working directory"
type: string
required: false
make_target:
description: "Make target for the contract"
type: string
required: false
package:
description: "Package to build"
type: string
required: false
release_name:
description: "Name for the release"
required: true
type: string
release_description:
description: "Description for the release"
required: false
type: string
home_domain:
description: "Home domain"
required: false
type: string
secrets:
release_token:
description: "Github token"
required: true
push:
tags:
- 'v*'
workflow_dispatch:

permissions: { }

permissions:
id-token: write
contents: write
attestations: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
# Environment gate
approve-release:
runs-on: ubuntu-latest
environment: publish-contract
permissions: { }
steps:
- uses: cargo-bins/cargo-binstall@main
- name: install scaffold-stellar
run: cargo binstall -y stellar-scaffold-cli
- name: Set working directory
run: |
RANDOM_DIR=$(openssl rand -hex 8)
WORK_DIR="${{ github.workspace }}/$RANDOM_DIR"
mkdir -p "$WORK_DIR"
echo "WORK_DIR=$WORK_DIR" >> $GITHUB_ENV
echo "Using working directory: $WORK_DIR"

- name: Checkout code
uses: actions/checkout@v6
with:
path: ${{ env.WORK_DIR }}

- name: Set relative path
run: |
# Set relative path after checking out the code
if [ "${{ inputs.relative_path }}" ]; then
WORK_DIR="$WORK_DIR/${{ inputs.relative_path }}"
echo "WORK_DIR=$WORK_DIR" >> $GITHUB_ENV
echo "Using relative path: $WORK_DIR"
fi

- name: Run Make (if applicable)
if: inputs.make_target != ''
working-directory: ${{ env.WORK_DIR }}
run: |
make ${{ inputs.make_target }}

- name: Update Rust and Add wasm32 Target
working-directory: ${{ env.WORK_DIR }}
run: |
rustup update
rustup target add wasm32v1-none

- name: Print versions
run: |
rustc --version
cargo --version

- name: Install jq
run: sudo apt-get update && sudo apt-get install -y jq

- name: Get Cargo.toml metadata
working-directory: ${{ env.WORK_DIR }}
run: |
if [ ! -f "Cargo.toml" ]; then
echo "Cargo.toml does not exist"
exit 1
fi
CARGO_METADATA=$(cargo metadata --format-version=1 --no-deps)
echo "CARGO_METADATA=$CARGO_METADATA" >> $GITHUB_ENV

- name: Set output directory path
run: |
RANDOM_DIR=$(openssl rand -hex 8)
OUTPUT="$WORK_DIR/$RANDOM_DIR"
echo "OUTPUT=$OUTPUT" >> $GITHUB_ENV

- name: Build contract
uses: stellar/stellar-cli@v27.0.0
with:
version: "27.0.0"
- run: |
# Navigate to the working directory
cd ${WORK_DIR}

# Build command arguments
COMMAND_ARGS="--out-dir ${OUTPUT} --meta source_repo=github:${{ github.repository }}"
if [ "${{ inputs.package }}" ]; then
COMMAND_ARGS="--package ${{ inputs.package }} $COMMAND_ARGS"
PACKAGE_NAME=${{ inputs.package }}
else
PACKAGE_NAME=$(grep -m1 '^name =' Cargo.toml | cut -d '"' -f2)
fi
if [ "${{ inputs.home_domain }}" ]; then
COMMAND_ARGS="$COMMAND_ARGS --meta home_domain=${{ inputs.home_domain }}"
fi

if [ "${{ inputs.profile }}" ]; then
COMMAND_ARGS="--profile ${{ inputs.profile }} $COMMAND_ARGS"
else
COMMAND_ARGS="--profile release $COMMAND_ARGS"
fi

# Build the contract
stellar scaffold build $COMMAND_ARGS

# Get the package version
PACKAGE_VERSION=$(echo "$CARGO_METADATA" | jq '.packages[] | select(.name == "'"${PACKAGE_NAME}"'") | .version' | sed -e 's/"//g')
if [ -z "$PACKAGE_VERSION" ]; then
echo "ERROR: Failed to get the package version"
exit 1
fi

# Build the wasm file name
WASM_FILE_NAME="${PACKAGE_NAME}_v${PACKAGE_VERSION}.wasm"

# Navigate to the output directory
cd ${OUTPUT}

# Find the .wasm file and copy it as unoptimized.wasm for hash calculation
find ${OUTPUT} -name "*.wasm" -exec cp {} ${WASM_FILE_NAME} \;
stellar contract optimize --wasm ${WASM_FILE_NAME} --wasm-out ${WASM_FILE_NAME}

# Calculate the hash of the wasm file
WASM_HASH=$(sha256sum $WASM_FILE_NAME | cut -d ' ' -f 1)

# Set environment variables
echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV
echo "WASM_FILE_NAME=$WASM_FILE_NAME" >> $GITHUB_ENV
echo "WASM_HASH=$WASM_HASH" >> $GITHUB_ENV
echo "PACKAGE_NAME=$PACKAGE_NAME" >> $GITHUB_ENV
echo "BUILD_INFO=$BUILD_INFO" >> $GITHUB_ENV

- name: Build release name
run: |
CLI_VERSION=$(stellar --version | grep -oP 'stellar \K\S+')
if [ -n "${{ inputs.relative_path }}" ]; then
relative_path=$(echo "_${{ inputs.relative_path }}" | sed 's/\W\+/_/g')
fi

# Check if the release_name input is equal to PACKAGE_VERSION
if [ "${{ inputs.release_name }}" != "${PACKAGE_VERSION}" ] && [ "${{ inputs.release_name }}" != "v${PACKAGE_VERSION}" ]; then
pkg_version="_pkg${PACKAGE_VERSION}"
else
pkg_version=""
fi

TAG_NAME="${{ inputs.release_name }}"
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV

- name: Create release
working-directory: ${{ env.OUTPUT }}
env:
GH_TOKEN: ${{ secrets.release_token }}
run: |
gh release create "${{ env.TAG_NAME }}" "${{ env.OUTPUT }}/${{ env.WASM_FILE_NAME }}" \
--title "${{ env.TAG_NAME }}" \
--notes "${{ inputs.release_description }}"
shell: bash

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "14"

- name: Build output
run: |
JSON_OUTPUT=$(node -e "console.log(JSON.stringify({
wasm: process.env.WASM,
hash: process.env.HASH,
relPath: (process.env.REL_PATH || undefined),
package: (process.env.PACKAGE || undefined),
make: (process.env.MAKE || undefined)
}))")
echo "WASM_OUTPUT='$JSON_OUTPUT'" >> $GITHUB_ENV
env:
REL_PATH: ${{ inputs.relative_path }}
PACKAGE: ${{ inputs.package }}
MAKE: ${{ inputs.make_target }}
HASH: ${{ env.WASM_HASH }}
WASM: ${{ env.WASM_FILE_NAME }}

- name: Output WASM ${{ env.WASM_OUTPUT }}
run: echo ${{ env.WASM_OUTPUT }}

- name: Send release info
run: |
JSON_OBJECT=$(node -e "console.log(JSON.stringify({
repository: process.env.REPOSITORY,
commitHash: process.env.COMMIT_HASH,
jobId: process.env.JOB_ID,
runId: process.env.RUN_ID,
contractHash: process.env.CONTRACT_HASH,
relativePath: process.env.RELATIVE_PATH || undefined,
packageName: process.env.PACKAGE_NAME || undefined,
makeTarget: process.env.MAKE_TARGET || undefined
}))")

echo "JSON to send: $JSON_OBJECT"

curl -X POST "https://api.stellar.expert/explorer/public/contract-validation/match" \
-H "Content-Type: application/json" \
-d "$JSON_OBJECT" \
--max-time 15
env:
REPOSITORY: ${{ github.server_url }}/${{ github.repository }}
COMMIT_HASH: ${{ github.sha }}
JOB_ID: ${{ github.job }}
RUN_ID: ${{ github.run_id }}
CONTRACT_HASH: ${{ env.WASM_HASH }}
RELATIVE_PATH: ${{ inputs.relative_path }}
PACKAGE_NAME: ${{ inputs.package }}
MAKE_TARGET: ${{ inputs.make_target }}

- name: Attest
uses: actions/attest-build-provenance@v3
with:
subject-path: "${{ env.OUTPUT }}/${{ env.WASM_FILE_NAME }}"
subject-name: "${{ env.WASM_FILE_NAME }}"
- run: echo "Approved release"

release-contract:
needs: approve-release
permissions:
id-token: write # OIDC token for build-provenance attestation
contents: write # in order to create releases
attestations: write
name: Compile Stellar smart contract for production and create release
uses: stellar-expert/soroban-build-workflow/.github/workflows/release.yml@e43b241f114bcf02151c30d61088506c6ad3ae0b
with:
release_name: ${{ github.ref_name }}
release_description: "Registry contract release"
home_domain: 'rgstry.xyz'
relative_path: 'contracts/registry'
package: 'registry'
secrets:
release_token: ${{ secrets.GITHUB_TOKEN }}
Loading