LocalTunnel in CI/CD Pipelines
LocalTunnel can be a powerful tool in your CI/CD workflows, especially for testing integrations that require public endpoints.
Use Cases in CI/CD
1. Webhook Testing
Test webhook integrations automatically in your CI pipeline.
2. External Service Integration
Test connections to external APIs that require callbacks.
3. End-to-End Testing
Run comprehensive tests that involve external services.
4. Staging Environment Simulation
Create temporary public endpoints for testing.
GitHub Actions Example
name: Integration Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: |
npm install
npm install -g localtunnel
- name: Start application
run: npm start &
- name: Wait for app to start
run: sleep 10
- name: Create tunnel
run: |
lt --port 3000 --subdomain ci-test-${{ github.run_id }} &
sleep 5
- name: Run integration tests
env:
TUNNEL_URL: https://ci-test-${{ github.run_id }}.loca.lt
run: npm test:integration
- name: Cleanup
if: always()
run: |
pkill -f localtunnel
pkill -f "npm start"
Jenkins Pipeline
pipeline {
agent any
stages {
stage('Setup') {
steps {
sh 'npm install'
sh 'npm install -g localtunnel'
}
}
stage('Start Services') {
steps {
sh 'npm start &'
sh 'sleep 10'
}
}
stage('Create Tunnel') {
steps {
script {
env.TUNNEL_SUBDOMAIN = "ci-${env.BUILD_ID}"
sh "lt --port 3000 --subdomain ${env.TUNNEL_SUBDOMAIN} &"
sh 'sleep 5'
}
}
}
stage('Integration Tests') {
steps {
sh 'npm run test:integration'
}
}
}
post {
always {
sh 'pkill -f localtunnel || true'
sh 'pkill -f "npm start" || true'
}
}
}
Docker Integration
# Dockerfile.ci
FROM node:16
WORKDIR /app
COPY package*.json ./
RUN npm install
RUN npm install -g localtunnel
COPY . .
# Script to start app and tunnel
COPY start-with-tunnel.sh ./
RUN chmod +x start-with-tunnel.sh
CMD ["./start-with-tunnel.sh"]
#!/bin/bash
# start-with-tunnel.sh
# Start the application
npm start &
APP_PID=$!
# Wait for app to start
sleep 10
# Start tunnel
lt --port 3000 --subdomain ci-${CI_BUILD_ID} &
TUNNEL_PID=$!
# Wait for tunnel to be ready
sleep 5
# Run tests
npm test:integration
# Cleanup
kill $APP_PID $TUNNEL_PID
Best Practices for CI/CD
1. Unique Subdomains
Always use unique subdomains to avoid conflicts:
SUBDOMAIN="ci-${CI_PIPELINE_ID}-${CI_JOB_ID}"
lt --port 3000 --subdomain $SUBDOMAIN
2. Health Checks
Verify tunnel is working before running tests:
// health-check.js
const axios = require('axios');
async function checkTunnel(url) {
try {
const response = await axios.get(`${url}/health`);
return response.status === 200;
} catch (error) {
return false;
}
}
3. Timeout Handling
Set reasonable timeouts for tunnel creation:
timeout 30s lt --port 3000 --subdomain ci-test || exit 1
4. Cleanup Procedures
Always clean up resources:
cleanup() {
echo "Cleaning up..."
pkill -f localtunnel
pkill -f "npm start"
}
trap cleanup EXIT
Advanced Configurations
Parallel Testing
Run multiple tunnels for parallel test execution:
strategy:
matrix:
test-suite: [auth, api, webhooks]
steps:
- name: Create tunnel for ${{ matrix.test-suite }}
run: |
lt --port ${{ matrix.port }} --subdomain ci-${{ matrix.test-suite }}-${{ github.run_id }} &
Environment-Specific Tunnels
// ci-config.js
const config = {
development: {
tunnelSubdomain: null
},
ci: {
tunnelSubdomain: `ci-${process.env.CI_BUILD_ID}`
},
testing: {
tunnelSubdomain: `test-${Date.now()}`
}
};
Monitoring and Reporting
Track tunnel usage in CI:
// tunnel-monitor.js
const fs = require('fs');
function logTunnelMetrics(url, startTime, endTime) {
const metrics = {
url,
duration: endTime - startTime,
timestamp: new Date().toISOString()
};
fs.appendFileSync('tunnel-metrics.json', JSON.stringify(metrics) + '
');
}
LocalTunnel can significantly enhance your CI/CD workflows when used properly!