Skip to content

Commit 7de55b4

Browse files
Add clean deployment workflow with tx tracking
1 parent d712f0a commit 7de55b4

5 files changed

Lines changed: 280 additions & 0 deletions

File tree

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
name: Full Deployment Pipeline
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
inputs:
8+
environment:
9+
description: 'Deployment Environment'
10+
required: true
11+
default: 'mainnet'
12+
type: choice
13+
options:
14+
- mainnet
15+
- devnet
16+
17+
env:
18+
SOLANA_CLI_VERSION: '1.18.26'
19+
NODE_VERSION: '20'
20+
21+
jobs:
22+
deploy:
23+
runs-on: ubuntu-latest
24+
outputs:
25+
tx_hash: ${{ steps.deploy.outputs.tx_hash }}
26+
program_id: ${{ steps.deploy.outputs.program_id }}
27+
controller: ${{ steps.deploy.outputs.controller }}
28+
29+
steps:
30+
- uses: actions/checkout@v4
31+
with:
32+
submodules: recursive
33+
fetch-depth: 0
34+
35+
- name: Setup Node.js
36+
uses: actions/setup-node@v4
37+
with:
38+
node-version: ${{ env.NODE_VERSION }}
39+
40+
- name: Install Solana CLI
41+
run: |
42+
sh -c "$(curl -sSfL https://release.solana.com/v${{ env.SOLANA_CLI_VERSION }}/install)"
43+
echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
44+
45+
- name: Configure Solana
46+
run: |
47+
solana config set --url ${{ github.event.inputs.environment == 'devnet' && 'https://api.devnet.solana.com' || 'https://api.mainnet-beta.solana.com' }}
48+
echo "${{ secrets.SOLANA_DEPLOYER_KEY }}" > deployer-key.json
49+
solana config set --keypair deployer-key.json
50+
51+
- name: Install Dependencies
52+
run: |
53+
npm install -g @solana/web3.js @coral-xyz/anchor-cli
54+
npm install --save-dev
55+
56+
- name: Deploy Contracts
57+
id: deploy
58+
env:
59+
HELIUS_API_KEY: ${{ secrets.HELIUS_API_KEY }}
60+
QUICKNODE_ENDPOINT: ${{ secrets.QUICKNODE_ENDPOINT }}
61+
run: |
62+
TIMESTAMP=$(date +%s)
63+
64+
# Deploy and capture output
65+
DEPLOY_OUTPUT=$(solana program deploy \
66+
--program-id GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz \
67+
--upgrade-authority FsQPFuje4WMdvbyoVef6MRMuzNZt9E8HM9YBN8T3Zbdq \
68+
--max-sign-attempts 50 \
69+
--use-rpc 2>&1)
70+
71+
# Extract transaction signature
72+
TX_HASH=$(echo "$DEPLOY_OUTPUT" | grep -oP 'Signature: \K[A-Za-z0-9]+' | head -1)
73+
PROGRAM_ID="GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz"
74+
CONTROLLER="FsQPFuje4WMdvbyoVef6MRMuzNZt9E8HM9YBN8T3Zbdq"
75+
76+
echo "tx_hash=$TX_HASH" >> $GITHUB_OUTPUT
77+
echo "program_id=$PROGRAM_ID" >> $GITHUB_OUTPUT
78+
echo "controller=$CONTROLLER" >> $GITHUB_OUTPUT
79+
echo "timestamp=$TIMESTAMP" >> $GITHUB_OUTPUT
80+
81+
# Save deployment report
82+
cat > deployment-report.json <<EOF
83+
{
84+
"timestamp": "$TIMESTAMP",
85+
"transaction": "$TX_HASH",
86+
"programId": "$PROGRAM_ID",
87+
"controller": "$CONTROLLER",
88+
"environment": "${{ github.event.inputs.environment || 'mainnet' }}",
89+
"deployer": "$(solana address)",
90+
"slot": "$(solana slot)"
91+
}
92+
EOF
93+
94+
- name: Verify Deployment
95+
run: |
96+
sleep 5
97+
solana program show GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz
98+
solana transaction-history ${{ steps.deploy.outputs.tx_hash }}
99+
100+
- name: Update Controller
101+
if: success()
102+
run: |
103+
node scripts/update-controller.js \
104+
--program-id ${{ steps.deploy.outputs.program_id }} \
105+
--controller ${{ steps.deploy.outputs.controller }} \
106+
--tx-hash ${{ steps.deploy.outputs.tx_hash }}
107+
108+
- name: Upload Deployment Artifacts
109+
uses: actions/upload-artifact@v4
110+
with:
111+
name: deployment-report-${{ steps.deploy.outputs.timestamp }}
112+
path: |
113+
deployment-report.json
114+
Deployer-Gene/.cache/*.json
115+
116+
- name: Create Release
117+
if: github.event_name == 'push'
118+
uses: actions/create-release@v1
119+
env:
120+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
121+
with:
122+
tag_name: deploy-${{ steps.deploy.outputs.timestamp }}
123+
release_name: Deployment ${{ steps.deploy.outputs.timestamp }}
124+
body: |
125+
## Deployment Summary
126+
127+
**Transaction Hash:** `${{ steps.deploy.outputs.tx_hash }}`
128+
**Program ID:** `${{ steps.deploy.outputs.program_id }}`
129+
**Controller:** `${{ steps.deploy.outputs.controller }}`
130+
**Environment:** ${{ github.event.inputs.environment || 'mainnet' }}
131+
132+
[View on Solscan](https://solscan.io/tx/${{ steps.deploy.outputs.tx_hash }})
133+
134+
notify:
135+
needs: deploy
136+
runs-on: ubuntu-latest
137+
if: always()
138+
steps:
139+
- name: Deployment Status
140+
run: |
141+
if [ "${{ needs.deploy.result }}" == "success" ]; then
142+
echo "✅ Deployment successful!"
143+
echo "TX: ${{ needs.deploy.outputs.tx_hash }}"
144+
echo "Program: ${{ needs.deploy.outputs.program_id }}"
145+
echo "Controller: ${{ needs.deploy.outputs.controller }}"
146+
else
147+
echo "❌ Deployment failed"
148+
exit 1
149+
fi
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Verify Deployment
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Full Deployment Pipeline"]
6+
types: [completed]
7+
8+
jobs:
9+
verify:
10+
runs-on: ubuntu-latest
11+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Setup Node.js
17+
uses: actions/setup-node@v4
18+
with:
19+
node-version: '20'
20+
21+
- name: Download Artifacts
22+
uses: actions/download-artifact@v4
23+
with:
24+
pattern: deployment-report-*
25+
merge-multiple: true
26+
27+
- name: Verify on Solscan
28+
run: |
29+
if [ -f deployment-report.json ]; then
30+
TX_HASH=$(jq -r '.transaction' deployment-report.json)
31+
PROGRAM_ID=$(jq -r '.programId' deployment-report.json)
32+
33+
echo "🔍 Verifying deployment..."
34+
echo "Transaction: https://solscan.io/tx/$TX_HASH"
35+
echo "Program: https://solscan.io/account/$PROGRAM_ID"
36+
37+
# Verify transaction exists
38+
curl -s "https://api.solscan.io/transaction?tx=$TX_HASH" | jq .
39+
fi
40+
41+
- name: Update README
42+
run: |
43+
if [ -f deployment-report.json ]; then
44+
TX_HASH=$(jq -r '.transaction' deployment-report.json)
45+
TIMESTAMP=$(jq -r '.timestamp' deployment-report.json)
46+
47+
cat >> DEPLOYMENT_LOG.md <<EOF
48+
## Deployment $(date -d @$TIMESTAMP +"%Y-%m-%d %H:%M:%S")
49+
50+
- **TX Hash:** [\`$TX_HASH\`](https://solscan.io/tx/$TX_HASH)
51+
- **Status:** ✅ Verified
52+
- **Workflow:** [Run #${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
53+
54+
EOF
55+
56+
git config user.name "GitHub Actions"
57+
git config user.email "actions@github.com"
58+
git add DEPLOYMENT_LOG.md
59+
git commit -m "Update deployment log [skip ci]" || true
60+
git push || true
61+
fi

DEPLOYMENT_LOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Deployment Log
2+
3+
This file tracks all successful deployments with transaction hashes and verification links.
4+
5+
---
6+
7+
## Initial Setup - 2025-01-13
8+
9+
- **Program ID:** `GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz`
10+
- **Controller:** `FsQPFuje4WMdvbyoVef6MRMuzNZt9E8HM9YBN8T3Zbdq`
11+
- **Status:** Ready for deployment
12+
13+
---

package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "github-mcp-server-deployment",
3+
"version": "2.0.0",
4+
"private": true,
5+
"scripts": {
6+
"deploy": "node scripts/update-controller.js",
7+
"verify": "solana program show GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz"
8+
},
9+
"devDependencies": {
10+
"@solana/web3.js": "^1.95.8",
11+
"@coral-xyz/anchor": "^0.30.1"
12+
}
13+
}

scripts/update-controller.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env node
2+
const { Connection, PublicKey, Keypair } = require('@solana/web3.js');
3+
const fs = require('fs');
4+
5+
async function updateController(programId, controller, txHash) {
6+
const connection = new Connection(process.env.SOLANA_RPC || 'https://api.mainnet-beta.solana.com');
7+
8+
const report = {
9+
timestamp: new Date().toISOString(),
10+
programId,
11+
controller,
12+
txHash,
13+
verified: false
14+
};
15+
16+
try {
17+
const tx = await connection.getTransaction(txHash, { maxSupportedTransactionVersion: 0 });
18+
if (tx) {
19+
report.verified = true;
20+
report.slot = tx.slot;
21+
report.blockTime = tx.blockTime;
22+
}
23+
24+
const programInfo = await connection.getAccountInfo(new PublicKey(programId));
25+
if (programInfo) {
26+
report.programDataSize = programInfo.data.length;
27+
report.programOwner = programInfo.owner.toBase58();
28+
}
29+
30+
fs.writeFileSync('controller-update.json', JSON.stringify(report, null, 2));
31+
console.log('✅ Controller updated successfully');
32+
console.log(JSON.stringify(report, null, 2));
33+
} catch (error) {
34+
console.error('❌ Controller update failed:', error.message);
35+
process.exit(1);
36+
}
37+
}
38+
39+
const args = process.argv.slice(2);
40+
const programId = args[args.indexOf('--program-id') + 1];
41+
const controller = args[args.indexOf('--controller') + 1];
42+
const txHash = args[args.indexOf('--tx-hash') + 1];
43+
44+
updateController(programId, controller, txHash);

0 commit comments

Comments
 (0)