CI/CD Pipelines
Use NullBore in CI/CD pipelines for preview deploys, integration testing, or temporary access to build artifacts.
Preview deploys
Open a tunnel in your CI pipeline to create a preview URL for each PR:
# GitHub Actions example
- name: Start preview server
run: |
npm start &
sleep 5
- name: Open tunnel
run: |
nullbore open --port 3000 --name "pr-${{ github.event.number }}" --ttl 4h
echo "Preview: https://pr-${{ github.event.number }}.tunnel.nullbore.com"
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '🕳️ Preview: https://pr-${{ github.event.number }}.tunnel.nullbore.com'
})
Integration testing
Expose a local test server for external integration tests:
- name: Start and expose test server
run: |
./test-server &
nullbore open --port 8080 --name "test-${{ github.run_id }}" --ttl 30m --idle
- name: Run integration tests
run: |
ENDPOINT="https://test-${{ github.run_id }}.tunnel.nullbore.com" npm test
API-driven
For more control, use the REST API directly:
# Open
TUNNEL=$(curl -s -X POST https://tunnel.nullbore.com/v1/tunnels \
-H "Authorization: Bearer $NULLBORE_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"local_port\": 3000, \"name\": \"ci-${GITHUB_RUN_ID}\", \"ttl\": \"1h\"}")
TUNNEL_ID=$(echo $TUNNEL | jq -r .id)
TUNNEL_URL=$(echo $TUNNEL | jq -r '.slug')
echo "Tunnel: https://${TUNNEL_URL}.tunnel.nullbore.com"
# ... run tests ...
# Close
curl -X DELETE "https://tunnel.nullbore.com/v1/tunnels/${TUNNEL_ID}" \
-H "Authorization: Bearer $NULLBORE_API_KEY"
Tips
- Use
--idlemode so tunnels don't expire during long test runs - Use unique names per run (
pr-123,ci-456) to avoid conflicts - Store your API key as a CI secret (
NULLBORE_API_KEY) - Set reasonable TTLs — CI tunnels shouldn't live forever