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
138 changes: 138 additions & 0 deletions prepare-squads-release/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
name: "Prepare Squads Release"
description: "Creates Solana release buffers and assigns their authority to a Squads vault without creating a Squads proposal"
inputs:
program-id:
description: "Program ID to upgrade"
required: true
program:
description: "Program name"
required: true
rpc-url:
description: "Solana RPC URL"
required: true
keypair:
description: "Payer keypair used for buffer preparation. It does not need to be a Squads member."
required: true
squads-vault:
description: "Squads vault address to set as buffer authority"
required: true
metadata-path:
description: "Optional IDL or metadata JSON path for a program-metadata buffer"
required: false
default: ""
priority-fee:
description: "Priority fee in microlamports"
required: false
default: "100000"
program-buffer-max-sign-attempts:
description: "Maximum Solana CLI signing attempts for the program buffer"
required: false
default: "100"
program-buffer-write-timeout-minutes:
description: "Maximum minutes to let a single program buffer write run before printing diagnostics"
required: false
default: "55"
program-buffer-retry-attempts:
description: "Maximum program buffer write attempts"
required: false
default: "1"
program-buffer-use-rpc:
description: "Send program buffer write transactions through the configured RPC instead of validator TPUs"
required: false
default: "false"
export-verify-pda:
description: "Export a solana-verify PDA transaction for the Squads vault"
required: false
default: "false"
repo-url:
description: "GitHub repository URL for solana-verify PDA export"
required: false
default: ""
commit-hash:
description: "Git commit hash to verify against"
required: false
default: ""

outputs:
buffer:
description: "Created program buffer address"
value: ${{ steps.write-program-buffer.outputs.buffer }}
metadata-buffer:
description: "Created program-metadata buffer address"
value: ${{ steps.write-metadata-buffer.outputs.buffer }}
pda-tx:
description: "Base64-encoded verify PDA transaction"
value: ${{ steps.export-verify-pda.outputs.pda_tx }}

runs:
using: "composite"
steps:
- name: Validate inputs
shell: bash
run: |
if [ "${{ inputs.export-verify-pda }}" = "true" ] && [ -z "${{ inputs.repo-url }}" ]; then
echo "Error: repo-url is required when export-verify-pda is true"
exit 1
fi
if [ "${{ inputs.export-verify-pda }}" = "true" ] && [ -z "${{ inputs.commit-hash }}" ]; then
echo "Error: commit-hash is required when export-verify-pda is true"
exit 1
fi

- name: Write program buffer
id: write-program-buffer
uses: solana-developers/github-actions/write-program-buffer@main
with:
program-id: ${{ inputs.program-id }}
program: ${{ inputs.program }}
rpc-url: ${{ inputs.rpc-url }}
keypair: ${{ inputs.keypair }}
buffer-authority-address: ${{ inputs.squads-vault }}
priority-fee: ${{ inputs.priority-fee }}
max-sign-attempts: ${{ inputs.program-buffer-max-sign-attempts }}
write-timeout-minutes: ${{ inputs.program-buffer-write-timeout-minutes }}
retry-attempts: ${{ inputs.program-buffer-retry-attempts }}
use-rpc: ${{ inputs.program-buffer-use-rpc }}

- name: Write metadata buffer
id: write-metadata-buffer
if: inputs.metadata-path != ''
uses: solana-developers/github-actions/write-metadata-buffer@main
with:
idl-path: ${{ inputs.metadata-path }}
rpc-url: ${{ inputs.rpc-url }}
keypair: ${{ inputs.keypair }}
buffer-authority: ${{ inputs.squads-vault }}
priority-fees: ${{ inputs.priority-fee }}

- name: Export verify PDA transaction
id: export-verify-pda
if: inputs.export-verify-pda == 'true'
uses: solana-developers/github-actions/verify-build@15e43c56b2ad2047dde732d807082570de2b8486
with:
program-id: ${{ inputs.program-id }}
program: ${{ inputs.program }}
rpc-url: ${{ inputs.rpc-url }}
keypair: ${{ inputs.keypair }}
repo-url: ${{ inputs.repo-url }}
commit-hash: ${{ inputs.commit-hash }}
network: "mainnet"
use-squads: "true"
vault-address: ${{ inputs.squads-vault }}

- name: Write summary
shell: bash
run: |
echo "## Squads release buffers" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- Program: \`${{ inputs.program-id }}\`" >> $GITHUB_STEP_SUMMARY
echo "- Program buffer: \`${{ steps.write-program-buffer.outputs.buffer }}\`" >> $GITHUB_STEP_SUMMARY
if [ -n "${{ steps.write-metadata-buffer.outputs.buffer }}" ]; then
echo "- Metadata buffer: \`${{ steps.write-metadata-buffer.outputs.buffer }}\`" >> $GITHUB_STEP_SUMMARY
fi
if [ "${{ inputs.export-verify-pda }}" = "true" ]; then
echo "- Verify PDA transaction exported: \`true\`" >> $GITHUB_STEP_SUMMARY
fi
echo "- Buffer authority: \`${{ inputs.squads-vault }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Create the program upgrade from Squads using the buffer above. This action does not create a Squads proposal." >> $GITHUB_STEP_SUMMARY
44 changes: 43 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ There are three examples:

- [Anchor Program](https://github.com/Woody4618/anchor-github-action-example)
- [Native Program](https://github.com/Woody4618/native-solana-github-action-example)
- [Anchor Program using Squads](https://github.com/Woody4618/workflow-tutorial)
- [Anchor Program using Squads](https://github.com/Woody4618/workflow-tutorial)

### Required Secrets for specific actions

Expand Down Expand Up @@ -97,6 +97,25 @@ Customize the workflow to your needs!
- `buffer-authority-address`: Authority for the buffer
- `priority-fee`: Transaction priority fee

- `prepare-squads-release`: Creates release buffers for a Squads-controlled upgrade without creating a Squads proposal from CI

- Creates the program buffer
- Transfers program buffer authority to the Squads vault
- Optionally creates a program-metadata buffer and transfers its authority to the Squads vault
- Optionally exports a `solana-verify` PDA transaction using the Squads vault as uploader
- Does not require the deployer keypair to be a Squads member
- Inputs:
- `program-id`: Target program ID
- `program`: Program name
- `rpc-url`: Solana RPC endpoint
- `keypair`: Payer keypair used for buffer preparation
- `squads-vault`: Squads vault to set as buffer authority
- `metadata-path`: Optional IDL or metadata JSON path
- `priority-fee`: Transaction priority fee
- `export-verify-pda`: Export a verify PDA transaction
- `repo-url`: GitHub repository URL for the verify PDA transaction
- `commit-hash`: Git commit hash for the verify PDA transaction

- `write-idl-buffer`: Writes an Anchor IDL buffer that will then later be set either from the provided keypair or from the squads multisig
- Creates IDL buffer
- Sets up IDL authority
Expand All @@ -113,6 +132,7 @@ Customize the workflow to your needs!
These actions use the [program-metadata](https://github.com/solana-program/program-metadata) program to attach metadata (IDL, security.txt, etc.) to any Solana program. This is the newer alternative to Anchor's built-in IDL commands and supports any program, not just Anchor programs.

- `metadata-upload`: Writes metadata directly to a program or from a pre-created buffer

- Supports any seed type (idl, security, or custom)
- Handles both direct upload and Squads multisig workflows
- Can export transactions for Squads signing
Expand Down Expand Up @@ -148,6 +168,28 @@ These actions use the [program-metadata](https://github.com/solana-program/progr
- `idl-upload`: Either sets the Anchor IDL buffer or skips that in case of squads deploy
- `verify-build`: Verifies on-chain programs match source using solana-verify andthe osec api

### Squads buffer-only release

For teams that do not want to add a CI-owned keypair as a Squads proposer, use `prepare-squads-release`. The keypair only pays for buffer preparation transactions. The resulting program buffer is owned by the Squads vault, and the upgrade proposal can be created manually in Squads.

```yaml
- name: Prepare Squads release buffers
uses: solana-developers/github-actions/prepare-squads-release@main
with:
program: ${{ env.PROGRAM }}
program-id: ${{ env.PROGRAM_ID }}
rpc-url: ${{ env.RPC_URL }}
keypair: ${{ secrets.MAINNET_DEPLOYER_KEYPAIR }}
squads-vault: ${{ secrets.MAINNET_MULTISIG_VAULT }}
metadata-path: ./target/idl/${{ env.PROGRAM }}.json
priority-fee: ${{ inputs.priority-fee }}
export-verify-pda: "true"
repo-url: ${{ github.server_url }}/${{ github.repository }}
commit-hash: ${{ github.sha }}
```

After the action completes, use the program buffer from the job summary when creating the program upgrade in Squads.

## 📝 Todo List

### Program Verification
Expand Down
1 change: 0 additions & 1 deletion verify-build/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ runs:
echo "Network: ${{ github.event.inputs.network }}"
echo "Verify: ${{ github.event.inputs.verify }}"
echo "Has keypair: ${{ inputs.keypair != '' }}"
echo "RPC URL: ${{ inputs.rpc-url }}"
- name: Verify Build
shell: bash
Expand Down
13 changes: 13 additions & 0 deletions write-metadata-buffer/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,25 @@ runs:

echo "$OUTPUT"

if echo "$OUTPUT" | grep -q "\[Error\]"; then
echo "Error: program-metadata create-buffer reported a failed transaction"
exit 1
fi

BUFFER=$(echo "$OUTPUT" | grep -i "buffer:" | head -1 | grep -oE '[1-9A-HJ-NP-Za-km-z]{32,44}')
if [ -z "$BUFFER" ]; then
echo "Error: Could not extract buffer address from output"
exit 1
fi

if ! NO_COLOR=1 npx @solana-program/program-metadata@0.5.1 fetch-buffer "$BUFFER" \
--keypair ./deploy-keypair.json \
--rpc "${{ inputs.rpc-url }}" \
--raw >/dev/null 2>&1; then
echo "Error: Metadata buffer $BUFFER was not found after create-buffer"
exit 1
fi

echo "Found buffer: $BUFFER"
echo "buffer=$BUFFER" >> $GITHUB_OUTPUT

Expand Down
Loading