Skip to content

Fix validator manager tests: improve session key validation #68

Fix validator manager tests: improve session key validation

Fix validator manager tests: improve session key validation #68

Workflow file for this run

name: Create and publish a Docker image
# Configures this workflow to run every time a change is pushed to the branch called `main`.
on:
push:
branches: ['main']
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
# NOTE: Bootnode configurations are now dynamically generated from GitHub secrets
# to prevent peer ID collisions and follow external-only bootnode architecture
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
build-and-push-image:
runs-on: ubuntu-latest
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
permissions:
contents: write # Changed from read to write to allow pushing commits
packages: write
#
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Free up additional disk space on GitHub runner (~20-25 GB)
# Enhanced cleanup for Polkadot SDK builds without cache
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # 1.3.1
with:
android: true # 12 GB save
dotnet: true # 3 GB save
haskell: true # 2 GB save
large-packages: true # 4 GB save
swap-storage: false # Keep swap for large builds
# Set up Docker Buildx for efficient layer caching
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# ------------------------------------------------------------
# SECURITY: Derive peer IDs from GitHub secrets
# Private keys are decoded temporarily in memory, never logged
# ------------------------------------------------------------
- name: Derive bootnode peer IDs from secrets
run: |
set -euo pipefail
echo "🔐 Deriving bootnode peer IDs from GitHub secrets..."
# Install polkadot binary from official releases (most reliable)
echo "📥 Installing polkadot binary..."
POLKADOT_VERSION="v1.9.0"
wget -q "https://github.com/paritytech/polkadot-sdk/releases/download/polkadot-${POLKADOT_VERSION}/polkadot" -O polkadot
chmod +x polkadot
# Verify installation
./polkadot --version
# Helper: derive peer-id from a key file using polkadot
# Parse only last line (PeerID) to avoid logging sensitive data
derive_peer () {
./polkadot key inspect-node-key --file "$1" 2>/dev/null | tail -1
}
# Decode secrets to tmpfs (runner's /tmp is already tmpfs), derive IDs
BOOT1=$(mktemp)
BOOT2=$(mktemp)
trap 'rm -f "$BOOT1" "$BOOT2"' EXIT # always wipe
echo "${{ secrets.BOOTNODE1_KEY_B64 }}" | base64 -d > "$BOOT1"
echo "${{ secrets.BOOTNODE2_KEY_B64 }}" | base64 -d > "$BOOT2"
PEER1="$(derive_peer "$BOOT1")"
PEER2="$(derive_peer "$BOOT2")"
# Mask *right now* so nothing else can leak it
echo "::add-mask::$PEER1"
echo "::add-mask::$PEER2"
# Build JSON array (still invisible in logs because masked)
BOOTNODES_JSON=$(jq -cn --arg id1 "$PEER1" --arg id2 "$PEER2" '
[
"/dns4/bootnode1.fennel.network/tcp/30333/p2p/\($id1)",
"/dns4/bootnode2.fennel.network/tcp/30333/p2p/\($id2)"
]')
# Set environment variables for subsequent steps (use base64 for safety)
echo "EXTERNAL_BOOTNODES_B64=$(printf %s "$BOOTNODES_JSON" | base64 -w0)" >> $GITHUB_ENV
echo "BOOTNODE1_PEER_ID=$PEER1" >> $GITHUB_ENV
echo "BOOTNODE2_PEER_ID=$PEER2" >> $GITHUB_ENV
# Log success (peer IDs are masked)
echo "✅ Successfully derived peer IDs from secrets using official Parity container"
echo "🌐 Using external-only bootnode architecture (following Parity best practices)"
echo "📋 Bootnode configuration: [MASKED - using derived peer IDs]"
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,format=long
# ------------------------------------------------------------
# Build the runtime deterministically with srtool and capture
# its SHA-256 so we can inject it as an OCI label.
# ------------------------------------------------------------
- name: Build runtime with srtool & extract Wasm hash
id: wasm
run: |
set -euo pipefail
echo "🛠️ Running srtool to build compact runtime…"
# Build runtime inside srtool container (outputs verbose log to console)
docker run --rm \
-v "${PWD}":/build \
-e RUNTIME_DIR=runtime/fennel \
-e PACKAGE=fennel-node-runtime \
--workdir /build \
paritytech/srtool:1.84.1
# After the container exits the compiled Wasm lives in the mounted volume
HASH=$(sha256sum runtime/fennel/target/srtool/release/wbuild/fennel-node-runtime/fennel_node_runtime.compact.wasm | awk '{print "0x"$1}')
echo "WASM_HASH=$HASH" >> $GITHUB_ENV
echo "hash=$HASH" >> $GITHUB_OUTPUT
echo "✅ Deterministic Wasm hash: $HASH"
# Clean up srtool build artifacts to free disk space
- name: Clean up srtool artifacts
run: |
echo "=== Cleaning up srtool build artifacts ==="
# Remove intermediate build files but keep the final WASM
find runtime/fennel/target/srtool -type f -name "*.rlib" -delete || true
find runtime/fennel/target/srtool -type f -name "*.rmeta" -delete || true
find runtime/fennel/target/srtool -type d -name "deps" -exec rm -rf {} + || true
find runtime/fennel/target/srtool -type d -name "build" -exec rm -rf {} + || true
# Additional aggressive cleanup
echo "=== Additional cleanup ==="
# Remove Docker build cache and unused images
docker system prune -af --volumes || true
# Remove temporary files
sudo rm -rf /tmp/* || true
# Remove apt cache
sudo apt-get clean || true
echo "=== Disk usage after cleanup ==="
df -h
# ------------------------------------------------------------
# Generate chain specifications using chain-spec-builder
# ------------------------------------------------------------
- name: Install jq for JSON processing
run: |
sudo apt-get update && sudo apt-get install -y jq
echo "✅ Installed jq"
- name: Install chain-spec-builder
run: |
# Create directory for chain-spec-builder
mkdir -p "${HOME}/.cargo/bin"
# Use Parity's prebuilt container that has Rust, protoc, and all dependencies
docker run --rm \
-v "${PWD}":/build \
-v "${HOME}/.cargo/bin":/cargo-bin \
--workdir /build \
paritytech/ci-unified:latest \
bash -c "
cargo install staging-chain-spec-builder --locked --root /tmp/cargo-install && \
cp /tmp/cargo-install/bin/chain-spec-builder /cargo-bin/
"
echo "✅ Installed chain-spec-builder"
# Add cargo bin to PATH for subsequent steps
echo "${HOME}/.cargo/bin" >> $GITHUB_PATH
- name: Create development chain spec
run: |
set -euo pipefail
# Create development directory in chainspecs if it doesn't exist
mkdir -p chainspecs/development
# Debug: Check chain-spec-builder version and help
echo "Chain-spec-builder version:"
chain-spec-builder --version || echo "No version flag available"
echo -e "\nChain-spec-builder help:"
chain-spec-builder --help || echo "No help available"
echo -e "\nChain-spec-builder create help:"
chain-spec-builder create --help || echo "No create help available"
# Check if the runtime has a development preset
echo "Checking available presets..."
chain-spec-builder list-presets \
--runtime runtime/fennel/target/srtool/release/wbuild/fennel-node-runtime/fennel_node_runtime.compact.wasm || true
# Check if runtime exists
echo "Checking if runtime WASM exists..."
ls -la runtime/fennel/target/srtool/release/wbuild/fennel-node-runtime/fennel_node_runtime.compact.wasm || echo "Runtime WASM not found!"
# Generate development chain spec
echo "Creating development chain spec..."
chain-spec-builder \
-c chainspecs/development/development.json \
create \
-r runtime/fennel/target/srtool/release/wbuild/fennel-node-runtime/fennel_node_runtime.compact.wasm \
named-preset development
# Convert to raw format
echo "Converting to raw format..."
chain-spec-builder \
-c chainspecs/development/development-raw.json \
convert-to-raw \
chainspecs/development/development.json
# Verify the specs were created
echo "✅ Generated chain specifications:"
ls -l chainspecs/development/
# Quick verification of content
echo "Verifying development.json content:"
jq '.name' chainspecs/development/development.json || echo "Failed to parse JSON"
# Comprehensive verification
echo -e "\n📋 Verification of generated files:"
ls -l chainspecs/development/development.json chainspecs/development/development-raw.json
echo -e "\n📄 Chain spec structure (first 5 lines):"
jq . chainspecs/development/development.json 2>/dev/null | head -n 5 || true
echo -e "\n🔍 Checking file sizes:"
stat -c "development.json: %s bytes" chainspecs/development/development.json
stat -c "development-raw.json: %s bytes" chainspecs/development/development-raw.json
# Verify raw spec is SCALE-encoded (not JSON)
echo -e "\n🔬 Verifying raw spec format (first 200 bytes):"
head -c 200 chainspecs/development/development-raw.json | xxd | head -n 5 || echo "Could not read raw spec"
# Ensure files are not empty
if [ ! -s chainspecs/development/development.json ]; then
echo "❌ Error: development.json is empty!"
exit 1
fi
if [ ! -s chainspecs/development/development-raw.json ]; then
echo "❌ Error: development-raw.json is empty!"
exit 1
fi
echo "✅ All development chain spec files are populated"
- name: Inject bootnodes into development chain spec
run: |
set -euo pipefail
echo "🔗 Injecting dynamically derived bootnodes into development chain spec..."
TARGET="development"
SPEC="chainspecs/${TARGET}/development.json"
# Use external-only bootnodes (Parity's recommended approach)
# Both internal and external nodes use the same public endpoints
# Decode bootnodes from base64 (safe transport through GitHub Actions env)
EXTERNAL_BOOTNODES=$(echo "$EXTERNAL_BOOTNODES_B64" | base64 -d)
echo "📋 Using external-only bootnode architecture: [MASKED - derived peer IDs]"
# Only update if there are changes (idempotent)
CURRENT_BOOTNODES=$(jq -c '.bootNodes // []' "$SPEC")
if [ "$CURRENT_BOOTNODES" != "$EXTERNAL_BOOTNODES" ]; then
echo "📝 Updating bootNodes in ${TARGET} chain spec with derived peer IDs..."
jq --argjson arr "$EXTERNAL_BOOTNODES" '.bootNodes = $arr' "$SPEC" > tmp.json && mv tmp.json "$SPEC"
# Regenerate raw spec with bootnodes included
echo "🔄 Regenerating raw ${TARGET} spec with derived bootnodes..."
chain-spec-builder \
-c "chainspecs/${TARGET}/development-raw.json" \
convert-to-raw \
"chainspecs/${TARGET}/development.json"
echo "✅ Bootnodes updated successfully with derived peer IDs"
else
echo "✅ No changes needed - bootnodes already up to date"
fi
# Verify bootnodes configuration
echo "📊 Current bootNodes configuration:"
jq '.bootNodes' "$SPEC" || echo "No bootNodes found"
- name: Commit development chainspecs to repository
run: |
# Configure git
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
# Add the development chainspecs
git add chainspecs/development/development.json chainspecs/development/development-raw.json
# Check if there are changes to commit
if git diff --staged --quiet; then
echo "No changes to development chainspecs"
else
# Commit the changes with [ci skip] to prevent retriggering
git commit -m "Update development chainspecs with derived bootnode peer IDs [ci skip]
- Peer IDs derived from GitHub secrets (BOOTNODE1_KEY_B64, BOOTNODE2_KEY_B64)
- Using external-only bootnode architecture (Parity best practice)
- Bootnode 1: $BOOTNODE1_PEER_ID
- Bootnode 2: $BOOTNODE2_PEER_ID"
# Push the changes back to the repository
git push origin ${GITHUB_REF#refs/heads/}
echo "✅ Development chainspecs committed and pushed to repository on branch ${GITHUB_REF#refs/heads/}"
fi
- name: Create staging chain specs
run: |
set -euo pipefail
# Create staging directory in chainspecs if it doesn't exist
mkdir -p chainspecs/staging
# Generate staging chain spec
echo "Generating staging chain spec..."
chain-spec-builder \
-c chainspecs/staging/staging-chainspec.json \
create \
-r runtime/fennel/target/srtool/release/wbuild/fennel-node-runtime/fennel_node_runtime.compact.wasm \
named-preset staging
# Generate raw staging chain spec
echo "Generating raw staging chain spec..."
chain-spec-builder \
-c chainspecs/staging/staging-raw.json \
convert-to-raw \
chainspecs/staging/staging-chainspec.json
# Verify the staging specs were created
echo "✅ Generated staging chain specifications:"
ls -la chainspecs/staging/
# Quick verification of content
echo "Verifying staging-chainspec.json content:"
jq '.name' chainspecs/staging/staging-chainspec.json || echo "Failed to parse JSON"
# Comprehensive verification
echo -e "\n📋 Verification of generated files:"
ls -l chainspecs/staging/staging-chainspec.json chainspecs/staging/staging-raw.json
echo -e "\n📄 Chain spec structure (first 5 lines):"
jq . chainspecs/staging/staging-chainspec.json 2>/dev/null | head -n 5 || true
echo -e "\n🔍 Checking file sizes:"
stat -c "staging-chainspec.json: %s bytes" chainspecs/staging/staging-chainspec.json
stat -c "staging-raw.json: %s bytes" chainspecs/staging/staging-raw.json
# Verify raw spec is SCALE-encoded (not JSON)
echo -e "\n🔬 Verifying raw spec format (first 200 bytes):"
head -c 200 chainspecs/staging/staging-raw.json | xxd | head -n 5 || echo "Could not read raw spec"
# Ensure files are not empty
if [ ! -s chainspecs/staging/staging-chainspec.json ]; then
echo "❌ Error: staging-chainspec.json is empty!"
exit 1
fi
if [ ! -s chainspecs/staging/staging-raw.json ]; then
echo "❌ Error: staging-raw.json is empty!"
exit 1
fi
echo "✅ All staging chain spec files are populated"
- name: Inject bootnodes into staging chain spec
run: |
set -euo pipefail
echo "🔗 Injecting dynamically derived bootnodes into staging chain spec..."
TARGET="staging"
SPEC="chainspecs/${TARGET}/staging-chainspec.json"
# Use external-only bootnodes (Parity's recommended approach)
# Both internal and external nodes use the same public endpoints
# Decode bootnodes from base64 (safe transport through GitHub Actions env)
EXTERNAL_BOOTNODES=$(echo "$EXTERNAL_BOOTNODES_B64" | base64 -d)
echo "📋 Using external-only bootnode architecture: [MASKED - derived peer IDs]"
# Only update if there are changes (idempotent)
CURRENT_BOOTNODES=$(jq -c '.bootNodes // []' "$SPEC")
if [ "$CURRENT_BOOTNODES" != "$EXTERNAL_BOOTNODES" ]; then
echo "📝 Updating bootNodes in ${TARGET} chain spec with derived peer IDs..."
jq --argjson arr "$EXTERNAL_BOOTNODES" '.bootNodes = $arr' "$SPEC" > tmp.json && mv tmp.json "$SPEC"
# Regenerate raw spec with bootnodes included
echo "🔄 Regenerating raw ${TARGET} spec with derived bootnodes..."
chain-spec-builder \
-c "chainspecs/${TARGET}/staging-raw.json" \
convert-to-raw \
"chainspecs/${TARGET}/staging-chainspec.json"
echo "✅ Bootnodes updated successfully with derived peer IDs"
else
echo "✅ No changes needed - bootnodes already up to date"
fi
# Verify bootnodes configuration
echo "📊 Current bootNodes configuration:"
jq '.bootNodes' "$SPEC" || echo "No bootNodes found"
- name: Commit staging chainspecs to repository
run: |
# Configure git
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
# Add the staging chainspecs
git add chainspecs/staging/staging-chainspec.json chainspecs/staging/staging-raw.json
# Check if there are changes to commit
if git diff --staged --quiet; then
echo "No changes to staging chainspecs"
else
# Commit the changes with [ci skip] to prevent retriggering
git commit -m "Update staging chainspecs with derived bootnode peer IDs [ci skip]
- Peer IDs derived from GitHub secrets (BOOTNODE1_KEY_B64, BOOTNODE2_KEY_B64)
- Using external-only bootnode architecture (Parity best practice)
- Bootnode 1: $BOOTNODE1_PEER_ID
- Bootnode 2: $BOOTNODE2_PEER_ID"
# Push the changes back to the repository
git push origin ${GITHUB_REF#refs/heads/}
echo "✅ Staging chainspecs committed and pushed to repository on branch ${GITHUB_REF#refs/heads/}"
fi
- name: Upload chain specs as artifacts
uses: actions/upload-artifact@v4
with:
name: fennel-chainspecs
path: |
chainspecs/development/development.json
chainspecs/development/development-raw.json
chainspecs/staging/staging-chainspec.json
chainspecs/staging/staging-raw.json
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
- name: Build and push Docker image
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
WASM_HASH=${{ env.WASM_HASH }}
# Remove problematic cache settings that are causing the blob error
# cache-from: type=gha
# cache-to: type=gha,mode=max
provenance: false
# Create and upload artifact containing image info
- name: Output image info to artifact
run: |
mkdir -p ./artifacts
echo "Image name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" > ./artifacts/image-info.txt
echo "Tags: ${{ steps.meta.outputs.tags }}" >> ./artifacts/image-info.txt
echo "Wasm hash: ${{ env.WASM_HASH }}" >> ./artifacts/image-info.txt
echo "Digest: ${{ steps.build.outputs.digest }}" >> ./artifacts/image-info.txt
echo "Created: $(date -u +\"%Y-%m-%dT%H:%M:%SZ\")" >> ./artifacts/image-info.txt
- name: Upload Docker image info artifact
uses: actions/upload-artifact@v4
with:
name: fennel-node-image-info
path: ./artifacts/image-info.txt
# ------------------------------------------------------------
# Package and publish Helm chart with updated values
# ------------------------------------------------------------
- name: Install Helm
uses: azure/setup-helm@v3
with:
version: 'v3.13.0'
- name: Add Parity Helm repo
run: |
helm repo add parity https://paritytech.github.io/helm-charts
helm repo update
- name: Update Helm dependencies
run: |
cd Charts/fennel-node
helm dependency update
- name: Extract image tag from metadata
id: extract-tag
run: |
# Extract the sha-prefixed tag from the metadata
SHA_TAG=$(echo "${{ steps.meta.outputs.tags }}" | grep -oE 'sha-[a-f0-9]+' | head -1)
echo "tag=${SHA_TAG}" >> $GITHUB_OUTPUT
echo "✅ Extracted image tag: ${SHA_TAG}"
- name: Update base values.yaml
uses: fjogeleit/yaml-update-action@v0.13.2
with:
valueFile: 'Charts/fennel-node/values.yaml'
propertyPath: 'image.tag'
value: ${{ steps.extract-tag.outputs.tag }}
commitChange: false
- name: Update staging values.yaml
uses: fjogeleit/yaml-update-action@v0.13.2
with:
valueFile: 'Charts/fennel-node/values-staging.yaml'
propertyPath: 'image.tag'
value: ${{ steps.extract-tag.outputs.tag }}
commitChange: false
- name: Lint Helm chart
run: |
echo "🔍 Linting base chart..."
helm lint Charts/fennel-node
echo "🔍 Linting with staging values..."
helm lint Charts/fennel-node -f Charts/fennel-node/values-staging.yaml
- name: Package Helm chart
run: |
mkdir -p release
helm package Charts/fennel-node --destination release
echo "📦 Packaged chart:"
ls -la release/
- name: Configure Git for chart release
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Publish Helm chart to GitHub Pages
run: |
set -euo pipefail
echo "🚀 Publishing Helm chart to GitHub Pages..."
# Store current chart version
CHART_VERSION=$(grep '^version:' Charts/fennel-node/Chart.yaml | awk '{print $2}')
echo "Chart version: $CHART_VERSION"
# Create a temporary directory for gh-pages content
TEMP_DIR=$(mktemp -d)
echo "Working in temporary directory: $TEMP_DIR"
# Initialize git in temp directory
cd "$TEMP_DIR"
git init
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
# Add remote
git remote add origin "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
# Try to fetch existing gh-pages branch
if git ls-remote --heads origin gh-pages | grep -q gh-pages; then
echo "📥 Fetching existing gh-pages branch..."
git fetch origin gh-pages
git checkout gh-pages
else
echo "🆕 Creating new gh-pages branch..."
git checkout --orphan gh-pages
# Remove any files that might exist
git rm -rf . 2>/dev/null || true
fi
# Create directory structure for Helm repository
mkdir -p charts
# Copy the packaged chart
cp "${GITHUB_WORKSPACE}/release"/*.tgz charts/
# Generate Helm repository index
helm repo index charts --url "https://corruptedaesthetic.github.io/fennel-solonet"
# Create a simple index.html for the repository
cat > index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Fennel Node Helm Repository</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.header { color: #2c3e50; }
.code { background-color: #f4f4f4; padding: 10px; border-radius: 5px; }
.chart-list { margin-top: 20px; }
</style>
</head>
<body>
<h1 class="header">🌿 Fennel Node Helm Repository</h1>
<p>This repository contains Helm charts for the Fennel blockchain node.</p>
<h2>Usage</h2>
<div class="code">
<strong>Add this repository:</strong><br>
<code>helm repo add fennel https://corruptedaesthetic.github.io/fennel-solonet</code><br><br>
<strong>Update repositories:</strong><br>
<code>helm repo update</code><br><br>
<strong>Install Fennel node:</strong><br>
<code>helm install fennel-node fennel/fennel-node</code>
</div>
<h2>Available Charts</h2>
<div class="chart-list">
<ul>
<li><strong>fennel-node</strong> - Fennel blockchain node deployment</li>
</ul>
</div>
<h2>Repository Files</h2>
<ul>
<li><a href="charts/">charts/</a> - Chart packages and index</li>
<li><a href="charts/index.yaml">charts/index.yaml</a> - Helm repository index</li>
</ul>
<hr>
<p><small>Generated automatically by GitHub Actions</small></p>
</body>
</html>
EOF
# Create README for the repository
cat > README.md << EOF
# Fennel Node Helm Repository
This is the Helm repository for Fennel blockchain node charts.
## Usage
\`\`\`bash
# Add the repository
helm repo add fennel https://corruptedaesthetic.github.io/fennel-solonet
# Update repositories
helm repo update
# Install Fennel node
helm install fennel-node fennel/fennel-node
\`\`\`
## Available Charts
- **fennel-node** - Fennel blockchain node deployment chart
## Chart Version: $CHART_VERSION
Generated automatically by GitHub Actions.
EOF
# Show what we're about to commit
echo "📋 Repository structure:"
find . -type f | sort
echo "📄 Charts index content:"
cat charts/index.yaml
# Add all files
git add .
# Commit changes
if git diff --staged --quiet; then
echo "ℹ️ No changes to commit"
else
git commit -m "📦 Update Helm repository - fennel-node v$CHART_VERSION
- Added fennel-node chart version $CHART_VERSION
- Updated repository index
- Generated: $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
echo "📤 Pushing to gh-pages branch..."
git push origin gh-pages --force
echo "✅ Helm chart repository published successfully!"
echo "🌐 Repository URL: https://corruptedaesthetic.github.io/fennel-solonet"
echo "📊 Charts URL: https://corruptedaesthetic.github.io/fennel-solonet/charts"
fi
# Cleanup
cd "$GITHUB_WORKSPACE"
rm -rf "$TEMP_DIR"
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
release/*.tgz
./artifacts/image-info.txt
chainspecs/development/development.json
chainspecs/development/development-raw.json
chainspecs/staging/staging-chainspec.json
chainspecs/staging/staging-raw.json
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.6.0
with:
charts_dir: Charts
skip_existing: true
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- name: Upload Helm chart artifact
uses: actions/upload-artifact@v4
with:
name: fennel-helm-chart
path: release/*.tgz
retention-days: 30
- name: Output workflow summary
run: |
echo "## 📊 Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🐳 Docker Image" >> $GITHUB_STEP_SUMMARY
echo "- **Image**: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Tag**: \`${{ steps.extract-tag.outputs.tag }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Wasm Hash**: \`${{ env.WASM_HASH }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📋 Chain Specs" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Development chain spec generated" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Staging chain spec generated" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📦 Helm Chart" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Chart packaged and published" >> $GITHUB_STEP_SUMMARY
echo "- **Version**: \`$(helm show chart release/*.tgz | grep '^version:' | awk '{print $2}')\`" >> $GITHUB_STEP_SUMMARY