Why GitHub & GitHub Actions
Code hosting and CI/CD in one platform
The Problem
Software development requires multiple services: code hosting, CI/CD, issue tracking, code review, artifact storage. Traditionally, these were separate tools:
- GitHub/GitLab/Bitbucket for code
- Jenkins/CircleCI/TravisCI for CI/CD
- Jira/Linear for issues
- Artifactory/S3 for artifacts
Each integration is a potential failure point. Each service is another login, another bill, another thing to maintain.
Platform consolidation reduces operational overhead.
We needed a platform that:
- Hosts code with excellent collaboration tools
- Runs CI/CD natively, no external service
- Integrates with the tools we already use
- Has the ecosystem and community we need
Current Options
| Option | Pros | Cons |
|---|---|---|
| GitHub + External CIGitHub for code, Jenkins/CircleCI for CI. |
|
|
| GitLabAll-in-one platform: code, CI, issues, registry. |
|
|
| GitHub + GitHub ActionsNative CI/CD in the largest code hosting platform. |
|
|
Future Outlook
GitHub has won code hosting. The question is whether to use their native CI/CD or bolt on something else.
Actions is good enough—and getting better.
GitHub Actions started rough but has matured significantly. Reusable workflows, composite actions, and the marketplace make it genuinely powerful. For most projects, there's no reason to add Jenkins complexity.
The trend is toward platform consolidation. Fewer tools, fewer integrations, fewer things to break. GitHub + Actions + Packages + Issues covers 90% of needs.
AI is accelerating this. GitHub Copilot, Copilot for PRs, and AI-powered code review are all GitHub-native. The platform advantage compounds.
Our Decision
✓Why we chose this
- Native integrationWorkflows trigger on any GitHub event. No webhooks to configure.
- Actions marketplaceThousands of reusable actions. Most integrations are one line.
- Matrix buildsTest across OS, Node version, browser combinations easily.
- Generous free tierPublic repos unlimited. Private repos get 2000 minutes/month free.
×Trade-offs we accept
- YAML complexityComplex workflows become hard to maintain. Extract to composite actions.
- Minutes costHeavy CI usage on private repos can get expensive. Cache aggressively.
- DebuggingDebugging workflow failures is harder than local CI. Use act for local testing.
Motivation
We use GitHub for everything: code, issues, CI/CD, packages, project management. One platform, one login, one bill.
This isn't about GitHub being best at everything. It's about reducing integration overhead. When CI runs in the same platform as code review, context is preserved. When issues link to PRs automatically, tracking is effortless.
For AI-assisted development, GitHub's integrations are unmatched. Copilot suggestions during code review, automated PR descriptions, AI-powered security scanning—all native.
Recommendation
Repository setup:
- Enable branch protection on main
- Require PR reviews and status checks
- Enable Dependabot for security updates
- Use CODEOWNERS for automatic reviewers
CI/CD patterns:
- Use caching aggressively (bun install is fast, but cached is faster)
- Run lint/typecheck/test in parallel
- Deploy on merge to main, not on PR
- Use environments for staging/production separation
Cost optimization:
- Cache dependencies between runs
- Use larger runners for build-heavy jobs (faster = cheaper)
- Self-hosted runners for very high volume
Examples
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Typecheck
run: bun run typecheck
- name: Lint
run: bun run lint
- name: Test
run: bun test
build:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- run: bun install --frozen-lockfile
- run: bun run build
- uses: actions/upload-artifact@v4
with:
name: build
path: dist/Complete CI workflow for a Bun project. Tests run on every PR, build artifacts are uploaded. Parallel jobs, caching, and proper dependency ordering.
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- run: bun install --frozen-lockfile
- run: bun run build
- name: Deploy to production
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
run: |
echo "Deploying to production..."
# Your deployment script hereDeploy workflow with environment protection. Only runs on main branch. Secrets are scoped to the production environment.