Flyio ci integration
'Configure CI/CD pipelines for Fly.io with GitHub Actions, Docker builds,From its SKILL.md
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill flyio-ci-integrationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
3.9 KB, 934 tokens by cl100k_base, as published. Nobody here has run it
Fly.io CI Integration
Overview
Set up CI/CD for Fly.io edge deployments: run unit tests on every PR, deploy to staging on pull requests, and promote to production on merge to main. Fly.io uses Machines API for app management and deploy tokens for scoped CI authentication. CI pipelines build Docker images, deploy via flyctl, and run post-deploy health checks against the edge endpoints.
GitHub Actions Workflow
# .github/workflows/fly-ci.yml
name: Fly.io CI
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npm ci
- run: npm test -- --reporter=verbose
deploy:
if: github.ref == 'refs/heads/main'
needs: unit-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: fly deploy --ha=false
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
- name: Health check
run: |
sleep 10
curl -sf https://my-app.fly.dev/health || exit 1
Mock-Based Unit Tests
// tests/fly-service.test.ts
import { describe, it, expect, vi } from 'vitest';
import { scaleApp } from '../src/fly-service';
vi.mock('../src/fly-client', () => ({
FlyClient: vi.fn().mockImplementation(() => ({
listMachines: vi.fn().mockResolvedValue([
{ id: 'mch_abc', state: 'started', region: 'iad', config: { size: 'shared-cpu-1x' } },
{ id: 'mch_def', state: 'started', region: 'lhr', config: { size: 'shared-cpu-1x' } },
]),
scaleMachine: vi.fn().mockResolvedValue({ id: 'mch_abc', state: 'started' }),
getApp: vi.fn().mockResolvedValue({ name: 'my-app', status: 'deployed', hostname: 'my-app.fly.dev' }),
})),
}));
describe('Fly.io Service', () => {
it('scales app machines across regions', async () => {
const result = await scaleApp('my-app', { count: 3 });
expect(result.machines).toBeDefined();
expect(result.status).toBe('scaled');
});
});
Integration Tests
// tests/integration/fly.integration.test.ts
import { describe, it, expect } from 'vitest';
const hasToken = !!process.env.FLY_API_TOKEN;
describe.skipIf(!hasToken)('Fly.io Live API', () => {
it('lists apps via Machines API', async () => {
const res = await fetch('https://api.machines.dev/v1/apps', {
headers: { Authorization: `Bearer ${process.env.FLY_API_TOKEN}` },
});
expect(res.status).toBe(200);
const body = await res.json();
expect(body).toHaveProperty('apps');
});
});
Error Handling
| CI Issue | Cause | Fix |
|---|---|---|
FLY_API_TOKEN invalid | Token expired or revoked | Regenerate with fly tokens create deploy -a my-app |
| Deploy timeout | Image build too slow | Add Docker layer caching with --build-cache |
| Health check fails | App not ready after deploy | Increase sleep or use fly status --wait |
Machine stuck in replacing | Rolling deploy conflict | Run fly machines list and destroy orphaned machines |
| Region unavailable | Edge region at capacity | Set primary_region in fly.toml to a different region |
Resources
- Fly.io GitHub Actions
- Fly.io Machines API
- GitHub Actions Secrets
Next Steps
For deployment strategies, see flyio-deploy-integration.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.