Skip to content

Commit 207b184

Browse files
authored
Merge pull request #11 from systeminit/feat/implement-ci-environment-framework
feat: add restructured CI pipeline for tests on PR's
2 parents bcc39f1 + d78eb81 commit 207b184

File tree

12 files changed

+827
-100
lines changed

12 files changed

+827
-100
lines changed

.github/workflows/api-tests.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: API Tests
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
environment:
7+
required: true
8+
type: string
9+
10+
jobs:
11+
api-tests:
12+
name: API Tests (${{ inputs.environment }})
13+
runs-on: ubuntu-latest
14+
environment: ${{ inputs.environment }}
15+
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
20+
- name: Start PostgreSQL
21+
run: docker compose -f docker-compose.platform.yml up -d postgres-test
22+
23+
- name: Setup Deno
24+
uses: denoland/setup-deno@v1
25+
with:
26+
deno-version: v1.x
27+
28+
- name: Wait for PostgreSQL
29+
run: deno task ci check-postgres local 60
30+
31+
- name: Setup Node.js
32+
uses: actions/setup-node@v4
33+
with:
34+
node-version: '20'
35+
cache: 'npm'
36+
37+
- name: Install dependencies
38+
run: npm ci --workspace=@chips/api
39+
40+
- name: Generate Prisma Client
41+
run: npx prisma generate
42+
working-directory: packages/api
43+
44+
- name: Run migrations
45+
run: npx prisma migrate deploy
46+
working-directory: packages/api
47+
env:
48+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/chips_test
49+
50+
- name: Run tests
51+
run: npm test --workspace=@chips/api
52+
env:
53+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/chips_test
54+
NODE_ENV: test
55+
56+
- name: Stop PostgreSQL
57+
if: always()
58+
run: docker compose -f docker-compose.platform.yml down

.github/workflows/lint.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Lint
2+
3+
on:
4+
workflow_call:
5+
6+
jobs:
7+
lint:
8+
name: Lint
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Checkout code
13+
uses: actions/checkout@v4
14+
15+
- name: Setup Node.js
16+
uses: actions/setup-node@v4
17+
with:
18+
node-version: '20'
19+
cache: 'npm'
20+
21+
- name: Install dependencies
22+
run: npm ci --workspace=@chips/web
23+
24+
- name: Run linter
25+
run: npm run lint --workspace=@chips/web

.github/workflows/pr-ci.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: PR CI Pipeline
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
7+
jobs:
8+
lint:
9+
uses: ./.github/workflows/lint.yml
10+
11+
api-tests:
12+
uses: ./.github/workflows/api-tests.yml
13+
with:
14+
environment: sandbox
15+
16+
build-and-push:
17+
name: Build & Push
18+
runs-on: ubuntu-latest
19+
needs: [ lint, api-tests ]
20+
environment: sandbox
21+
permissions:
22+
id-token: write
23+
contents: read
24+
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v4
28+
29+
- name: Setup Node.js
30+
uses: actions/setup-node@v4
31+
with:
32+
node-version: '20'
33+
cache: 'npm'
34+
35+
- name: Install root dependencies
36+
run: npm ci
37+
38+
- name: Build API
39+
run: npm run build --workspace=@chips/api
40+
41+
- name: Build Web
42+
run: npm run build --workspace=@chips/web
43+
env:
44+
VITE_API_URL: ${{ vars.VITE_API_URL }}
45+
46+
- name: Setup Deno
47+
uses: denoland/setup-deno@v1
48+
with:
49+
deno-version: v1.x
50+
51+
- name: Generate image tag
52+
id: tag
53+
run: |
54+
TAG=$(deno task ci calver | tail -n 1)
55+
echo "tag=$TAG" >> $GITHUB_OUTPUT
56+
57+
#- name: Configure AWS credentials
58+
# uses: aws-actions/configure-aws-credentials@v4
59+
# with:
60+
# role-to-assume: ${{ vars.AWS_ROLE_ARN }}
61+
# aws-region: ${{ vars.AWS_REGION }}
62+
63+
#- name: Build and push images
64+
# run: deno task ci push-image sandbox ${{ steps.tag.outputs.tag }}

.github/workflows/test.yml

Lines changed: 0 additions & 100 deletions
This file was deleted.

ci/commands/build.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* Build command implementation
3+
*/
4+
5+
interface Config {
6+
environment: string;
7+
tag: string;
8+
viteApiUrl: string;
9+
}
10+
11+
async function runCommand(command: string[], description: string): Promise<void> {
12+
console.log(`🔧 ${description}`);
13+
console.log(` Command: ${command.join(' ')}`);
14+
15+
const process = new Deno.Command(command[0], {
16+
args: command.slice(1),
17+
stdout: "piped",
18+
stderr: "piped",
19+
});
20+
21+
const { code, stdout, stderr } = await process.output();
22+
23+
if (code !== 0) {
24+
console.error(`❌ Failed: ${description}`);
25+
console.error("STDOUT:", new TextDecoder().decode(stdout));
26+
console.error("STDERR:", new TextDecoder().decode(stderr));
27+
throw new Error(`Command failed: ${description}`);
28+
}
29+
30+
console.log(`✅ Success: ${description}`);
31+
}
32+
33+
function parseConfig(args: string[]): Config {
34+
if (args.length !== 2) {
35+
throw new Error("Usage: build <environment> <tag>\nExample: build sandbox 20231201120000-abc1234");
36+
}
37+
38+
const environment = args[0];
39+
const tag = args[1];
40+
const viteApiUrl = Deno.env.get("VITE_API_URL") || "http://localhost:3000";
41+
42+
return { environment, tag, viteApiUrl };
43+
}
44+
45+
async function buildDockerImages(config: Config): Promise<void> {
46+
const region = Deno.env.get("AWS_REGION") || "us-west-2";
47+
const accountId = Deno.env.get("AWS_ACCOUNT_ID");
48+
49+
if (!accountId) {
50+
throw new Error("AWS_ACCOUNT_ID environment variable not found. Make sure AWS credentials are configured.");
51+
}
52+
53+
const ecrRegistry = `${accountId}.dkr.ecr.${region}.amazonaws.com`;
54+
const apiImage = `${ecrRegistry}/tonys-chips-api`;
55+
const webImage = `${ecrRegistry}/tonys-chips-web`;
56+
57+
// Build API image
58+
await runCommand(
59+
["docker", "build", "-f", "docker/api.Dockerfile", "-t", `${apiImage}:${config.tag}`, "."],
60+
"Building API Docker image"
61+
);
62+
63+
await runCommand(
64+
["docker", "tag", `${apiImage}:${config.tag}`, `${apiImage}:latest`],
65+
"Tagging API image as latest"
66+
);
67+
68+
// Build Web image
69+
await runCommand(
70+
[
71+
"docker", "build",
72+
"-f", "docker/web.Dockerfile",
73+
"--build-arg", `VITE_API_URL=${config.viteApiUrl}`,
74+
"-t", `${webImage}:${config.tag}`,
75+
"."
76+
],
77+
"Building Web Docker image"
78+
);
79+
80+
await runCommand(
81+
["docker", "tag", `${webImage}:${config.tag}`, `${webImage}:latest`],
82+
"Tagging Web image as latest"
83+
);
84+
85+
console.log("");
86+
console.log("🎉 Successfully built Docker images:");
87+
console.log(` API: ${apiImage}:${config.tag}`);
88+
console.log(` Web: ${webImage}:${config.tag}`);
89+
}
90+
91+
export async function build(args: string[]): Promise<void> {
92+
console.log("🚀 Starting Docker image build process");
93+
94+
const config = parseConfig(args);
95+
96+
console.log(`📋 Configuration:`);
97+
console.log(` Environment: ${config.environment}`);
98+
console.log(` Tag: ${config.tag}`);
99+
console.log(` API URL: ${config.viteApiUrl}`);
100+
console.log("");
101+
102+
await buildDockerImages(config);
103+
}

0 commit comments

Comments
 (0)