CI/CD Integration
Deploy with GitHub Actions, GitLab CI, and other CI/CD platforms
GitHub Actions
Pipe works seamlessly with GitHub Actions. Install Pipe in your workflow, configure SSH access, and deploy.
Prerequisites
- SSH key with access to your deployment server(s)
- Docker installed on the remote host
- GitHub repository secrets configured
Basic Workflow
A simple workflow that deploys on push to the main branch.
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install Pipe
run: go install github.com/bjarneo/pipe@latest
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts
- name: Deploy
run: |
pipe \
--host ${{ secrets.DEPLOY_HOST }} \
--user ${{ secrets.DEPLOY_USER }} \
--ssh-key ~/.ssh/id_rsa \
--tag ${{ github.sha }}
${{ github.sha }} as the tag for traceability, or ${{ github.ref_name }} for branch/tag names.
Matrix Deploy (Multiple Servers)
Deploy to multiple servers in parallel using GitHub Actions matrix strategy. Perfect for deploying to a fleet of VMs or different environments.
Deploy to Multiple VMs
name: Deploy to Multiple Servers
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
server:
- host: server1.example.com
name: server-1
- host: server2.example.com
name: server-2
- host: server3.example.com
name: server-3
fail-fast: false
max-parallel: 3
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install Pipe
run: go install github.com/bjarneo/pipe@latest
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ matrix.server.host }} >> ~/.ssh/known_hosts
- name: Deploy to ${{ matrix.server.name }}
run: |
pipe \
--host ${{ matrix.server.host }} \
--user ${{ secrets.DEPLOY_USER }} \
--ssh-key ~/.ssh/id_rsa \
--tag ${{ github.sha }} \
--container-name app-${{ matrix.server.name }}
Matrix with Different Configurations
Deploy different services or configurations to different servers:
name: Deploy Services
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- host: api.example.com
service: api
port: 3000
dockerfile: Dockerfile.api
- host: web.example.com
service: web
port: 8080
dockerfile: Dockerfile.web
- host: worker.example.com
service: worker
port: 9000
dockerfile: Dockerfile.worker
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install Pipe
run: go install github.com/bjarneo/pipe@latest
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ matrix.host }} >> ~/.ssh/known_hosts
- name: Deploy ${{ matrix.service }}
run: |
pipe \
--host ${{ matrix.host }} \
--user deploy \
--ssh-key ~/.ssh/id_rsa \
--dockerfile ${{ matrix.dockerfile }} \
--image ${{ matrix.service }} \
--container-name ${{ matrix.service }} \
--container-port ${{ matrix.port }} \
--host-port ${{ matrix.port }} \
--tag ${{ github.sha }}
fail-fast: false to continue deploying to other servers even if one fails.
Environment-Based Deployment
Use GitHub Environments for staged deployments with approvals and environment-specific secrets.
name: Deploy with Environments
on:
push:
branches: [main]
release:
types: [published]
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install Pipe
run: go install github.com/bjarneo/pipe@latest
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ vars.DEPLOY_HOST }} >> ~/.ssh/known_hosts
- name: Deploy to Staging
run: |
pipe \
--host ${{ vars.DEPLOY_HOST }} \
--user ${{ secrets.DEPLOY_USER }} \
--ssh-key ~/.ssh/id_rsa \
--tag ${{ github.sha }} \
--env NODE_ENV=staging
deploy-production:
runs-on: ubuntu-latest
environment: production
needs: deploy-staging
if: github.event_name == 'release'
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install Pipe
run: go install github.com/bjarneo/pipe@latest
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ vars.DEPLOY_HOST }} >> ~/.ssh/known_hosts
- name: Deploy to Production
run: |
pipe \
--host ${{ vars.DEPLOY_HOST }} \
--user ${{ secrets.DEPLOY_USER }} \
--ssh-key ~/.ssh/id_rsa \
--tag ${{ github.event.release.tag_name }} \
--env NODE_ENV=production
Required Secrets
Configure these secrets in your GitHub repository settings (Settings → Secrets and variables → Actions):
| Secret | Description | Example |
|---|---|---|
SSH_PRIVATE_KEY |
Private SSH key for server access | Contents of ~/.ssh/id_rsa |
DEPLOY_HOST |
Target server hostname or IP | server.example.com |
DEPLOY_USER |
SSH username on the server | deploy |
Generating a Deploy Key
# Generate a new SSH key pair for deployments
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/deploy_key -N ""
# Copy the public key to your server
ssh-copy-id -i ~/.ssh/deploy_key.pub user@server.example.com
# Add the private key contents to GitHub Secrets
cat ~/.ssh/deploy_key
GitLab CI
Pipe also works with GitLab CI/CD pipelines.
stages:
- deploy
variables:
GO_VERSION: '1.21'
deploy:
stage: deploy
image: golang:${GO_VERSION}
only:
- main
before_script:
- go install github.com/bjarneo/pipe@latest
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H $DEPLOY_HOST >> ~/.ssh/known_hosts
script:
- pipe
--host $DEPLOY_HOST
--user $DEPLOY_USER
--ssh-key ~/.ssh/id_rsa
--tag $CI_COMMIT_SHA
deploy-matrix:
stage: deploy
image: golang:${GO_VERSION}
only:
- main
parallel:
matrix:
- SERVER: [server1.example.com, server2.example.com, server3.example.com]
before_script:
- go install github.com/bjarneo/pipe@latest
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H $SERVER >> ~/.ssh/known_hosts
script:
- pipe
--host $SERVER
--user $DEPLOY_USER
--ssh-key ~/.ssh/id_rsa
--tag $CI_COMMIT_SHA
JSON Output for CI
Use --json to get machine-readable output for CI/CD integration, notifications, or metrics.
- name: Deploy and notify
run: |
RESULT=$(pipe --host ${{ secrets.DEPLOY_HOST }} --user deploy --json)
DURATION=$(echo $RESULT | jq -r '.timing.duration')
TRANSFERRED=$(echo $RESULT | jq -r '.transfer.transferred')
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-H "Content-Type: application/json" \
-d "{\"text\": \"Deployed in ${DURATION} (transferred ${TRANSFERRED})\"}"
- name: Deploy with timeout check
run: |
RESULT=$(pipe --host ${{ secrets.DEPLOY_HOST }} --user deploy --json)
SECONDS=$(echo $RESULT | jq -r '.timing.total_seconds')
if (( $(echo "$SECONDS > 300" | bc -l) )); then
echo "Deployment took longer than 5 minutes!"
exit 1
fi
JSON Output Structure
{
"timing": {
"duration": "23.4s",
"total_seconds": 23.4,
"build": "8.2s",
"transfer": "12.1s",
"deploy": "3.1s"
},
"transfer": {
"transferred": "47MB",
"saved": "312MB",
"layers_changed": 3,
"layers_cached": 12
},
"image": {
"name": "my-app",
"tag": "abc1234"
},
"host": "server.example.com",
"success": true
}