Skip to content

Docker Publish

Docker Publish #37

name: Docker Publish
on:
workflow_run:
workflows:
- "CI build"
types:
- "completed"
jobs:
docker-test:
name: Build and test Docker image
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.workflow_run.head_sha }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Build for local platform only (amd64) and load into Docker for testing
- name: Build image for testing
uses: docker/build-push-action@v6
with:
context: .
load: true
tags: bitsocial-cli:test
secrets: |
github_token=${{ secrets.GITHUB_TOKEN }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Prepare compose files
run: cp .github/docker-compose.ci.yml docker-compose.yml
- name: Start services with docker compose
env:
BITSOCIAL_IMAGE: bitsocial-cli:test
run: docker compose up -d
- name: Wait for daemon to be ready
run: |
echo "Waiting for daemon to start..."
for i in $(seq 1 60); do
if docker compose exec -T bitsocial node -e "const net=require('net');const s=net.connect(9138,'localhost',()=>{s.end();process.exit(0)});s.on('error',()=>process.exit(1));setTimeout(()=>process.exit(1),3000)" 2>/dev/null; then
echo "Daemon is ready after ${i}s"
break
fi
if [ "$i" = "60" ]; then
echo "Daemon failed to start within 60s"
docker compose logs --no-color
exit 1
fi
sleep 1
done
- name: Verify WebSocket RPC is accessible
run: |
docker compose exec -T bitsocial node -e "
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:9138');
const timeout = setTimeout(() => { console.error('WebSocket connection timed out'); process.exit(1); }, 10000);
ws.on('open', () => { clearTimeout(timeout); console.log('WebSocket connected successfully'); ws.close(); process.exit(0); });
ws.on('error', (err) => { clearTimeout(timeout); console.error('WebSocket error:', err.message); process.exit(1); });
"
- name: Test CLI commands inside compose service
run: |
# Create a community
COMMUNITY_ADDRESS=$(docker compose exec -T bitsocial node ./bin/run community create --description "docker-ci-test" | tr -d '\r' | tail -n 1)
if [ -z "$COMMUNITY_ADDRESS" ]; then
echo "FAIL: community create did not return an address"
exit 1
fi
echo "Created community: $COMMUNITY_ADDRESS"
# Verify the created community can be loaded
COMMUNITY_JSON=$(docker compose exec -T bitsocial node ./bin/run community get "$COMMUNITY_ADDRESS" | tr -d '\r')
echo "$COMMUNITY_JSON" | EXPECTED_ADDRESS="$COMMUNITY_ADDRESS" node -e "
process.stdin.resume();
let data = '';
process.stdin.on('data', chunk => data += chunk);
process.stdin.on('end', () => {
const community = JSON.parse(data);
if (community.address !== process.env.EXPECTED_ADDRESS) {
console.error(\`FAIL: expected address '\${process.env.EXPECTED_ADDRESS}', got '\${community.address}'\`);
process.exit(1);
}
if (community.description !== 'docker-ci-test') {
console.error(\`FAIL: expected description 'docker-ci-test', got '\${community.description}'\`);
process.exit(1);
}
console.log('community get returned expected payload');
});
"
echo "All CLI commands passed inside docker compose service"
- name: Dump compose logs on failure
if: failure()
run: docker compose logs --no-color
- name: Stop and remove docker compose services
if: always()
run: docker compose down -v
docker-push:
name: Push Docker image
needs:
- docker-test
if: ${{ github.event.workflow_run.conclusion == 'success' && needs.docker-test.result == 'success' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.workflow_run.head_sha }}
- name: Get latest release tag
id: previoustag
uses: WyriHaximus/github-action-get-previous-tag@v1
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/bitsocialhq/bitsocial-cli
tags: |
type=semver,pattern={{version}},value=${{ steps.previoustag.outputs.tag }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.previoustag.outputs.tag }}
type=semver,pattern={{major}},value=${{ steps.previoustag.outputs.tag }}
type=raw,value=latest
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Full multi-arch build and push
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
secrets: |
github_token=${{ secrets.GITHUB_TOKEN }}
cache-from: type=gha
cache-to: type=gha,mode=max