diff --git a/.github/workflows/contract-release.yml b/.github/workflows/contract-release.yml index f996d2f..015c2b8 100644 --- a/.github/workflows/contract-release.yml +++ b/.github/workflows/contract-release.yml @@ -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 }}