mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Generated by Spark: GitHub/gitlab/Jenkins/circleci ci cd config
This commit is contained in:
264
.circleci/config.yml
Normal file
264
.circleci/config.yml
Normal file
@@ -0,0 +1,264 @@
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
node: circleci/node@5.2.0
|
||||
docker: circleci/docker@2.6.0
|
||||
slack: circleci/slack@4.13.3
|
||||
|
||||
executors:
|
||||
node-executor:
|
||||
docker:
|
||||
- image: cimg/node:20.11
|
||||
resource_class: large
|
||||
working_directory: ~/repo
|
||||
|
||||
playwright-executor:
|
||||
docker:
|
||||
- image: mcr.microsoft.com/playwright:v1.42.0-focal
|
||||
resource_class: large
|
||||
working_directory: ~/repo
|
||||
|
||||
commands:
|
||||
restore-dependencies:
|
||||
description: 'Restore npm dependencies from cache'
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v1-dependencies-{{ checksum "package-lock.json" }}
|
||||
- v1-dependencies-
|
||||
|
||||
save-dependencies:
|
||||
description: 'Save npm dependencies to cache'
|
||||
steps:
|
||||
- save_cache:
|
||||
paths:
|
||||
- node_modules
|
||||
key: v1-dependencies-{{ checksum "package-lock.json" }}
|
||||
|
||||
notify-slack-on-fail:
|
||||
description: 'Notify Slack on failure'
|
||||
steps:
|
||||
- slack/notify:
|
||||
event: fail
|
||||
template: basic_fail_1
|
||||
|
||||
notify-slack-on-success:
|
||||
description: 'Notify Slack on success'
|
||||
steps:
|
||||
- slack/notify:
|
||||
event: pass
|
||||
template: success_tagged_deploy_1
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
executor: node-executor
|
||||
steps:
|
||||
- checkout
|
||||
- restore-dependencies
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm ci
|
||||
- save-dependencies
|
||||
- run:
|
||||
name: Run ESLint
|
||||
command: npm run lint || echo "No lint script found"
|
||||
- run:
|
||||
name: TypeScript type check
|
||||
command: npx tsc --noEmit
|
||||
- notify-slack-on-fail
|
||||
|
||||
test:
|
||||
executor: node-executor
|
||||
steps:
|
||||
- checkout
|
||||
- restore-dependencies
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm ci
|
||||
- save-dependencies
|
||||
- run:
|
||||
name: Run unit tests
|
||||
command: npm test || echo "No test script found"
|
||||
- store_test_results:
|
||||
path: ./junit.xml
|
||||
- store_artifacts:
|
||||
path: coverage
|
||||
destination: coverage
|
||||
- notify-slack-on-fail
|
||||
|
||||
build:
|
||||
executor: node-executor
|
||||
steps:
|
||||
- checkout
|
||||
- restore-dependencies
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm ci
|
||||
- save-dependencies
|
||||
- run:
|
||||
name: Build application
|
||||
command: npm run build
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- dist
|
||||
- store_artifacts:
|
||||
path: dist
|
||||
destination: build
|
||||
- notify-slack-on-fail
|
||||
|
||||
e2e-test:
|
||||
executor: playwright-executor
|
||||
steps:
|
||||
- checkout
|
||||
- restore-dependencies
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm ci
|
||||
- save-dependencies
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Install Playwright browsers
|
||||
command: npx playwright install chromium
|
||||
- run:
|
||||
name: Run E2E tests
|
||||
command: npm run test:e2e || echo "No E2E tests configured"
|
||||
- store_test_results:
|
||||
path: playwright-report
|
||||
- store_artifacts:
|
||||
path: playwright-report
|
||||
destination: e2e-report
|
||||
- notify-slack-on-fail
|
||||
|
||||
security-scan:
|
||||
executor: node-executor
|
||||
steps:
|
||||
- checkout
|
||||
- restore-dependencies
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm ci
|
||||
- save-dependencies
|
||||
- run:
|
||||
name: Run npm audit
|
||||
command: npm audit --audit-level=moderate || true
|
||||
- run:
|
||||
name: Install Trivy
|
||||
command: |
|
||||
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
|
||||
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install trivy -y
|
||||
- run:
|
||||
name: Run Trivy scan
|
||||
command: trivy fs --exit-code 0 --no-progress --format json --output trivy-report.json .
|
||||
- store_artifacts:
|
||||
path: trivy-report.json
|
||||
destination: security/trivy-report.json
|
||||
- notify-slack-on-fail
|
||||
|
||||
docker-build-and-push:
|
||||
executor: docker/docker
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker:
|
||||
docker_layer_caching: true
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Build Docker image
|
||||
command: |
|
||||
docker build -t ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:$CIRCLE_BRANCH .
|
||||
docker tag ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:$CIRCLE_BRANCH \
|
||||
ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:$CIRCLE_BRANCH-$CIRCLE_SHA1
|
||||
- run:
|
||||
name: Push to registry
|
||||
command: |
|
||||
echo $DOCKER_PASSWORD | docker login ghcr.io -u $DOCKER_USERNAME --password-stdin
|
||||
docker push ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:$CIRCLE_BRANCH
|
||||
docker push ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:$CIRCLE_BRANCH-$CIRCLE_SHA1
|
||||
if [ "$CIRCLE_BRANCH" = "main" ]; then
|
||||
docker tag ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:$CIRCLE_BRANCH \
|
||||
ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:latest
|
||||
docker push ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:latest
|
||||
fi
|
||||
- notify-slack-on-fail
|
||||
|
||||
deploy-staging:
|
||||
executor: node-executor
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Deploy to staging
|
||||
command: |
|
||||
echo "Deploying to staging environment..."
|
||||
echo "Image: ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:develop-$CIRCLE_SHA1"
|
||||
curl -X POST $STAGING_WEBHOOK_URL \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"image\":\"ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:develop\",\"sha\":\"$CIRCLE_SHA1\"}"
|
||||
- notify-slack-on-success
|
||||
- notify-slack-on-fail
|
||||
|
||||
deploy-production:
|
||||
executor: node-executor
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Deploy to production
|
||||
command: |
|
||||
echo "Deploying to production environment..."
|
||||
echo "Image: ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:latest"
|
||||
curl -X POST $PRODUCTION_WEBHOOK_URL \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"image\":\"ghcr.io/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:latest\",\"sha\":\"$CIRCLE_SHA1\"}"
|
||||
- notify-slack-on-success
|
||||
- notify-slack-on-fail
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build-test-deploy:
|
||||
jobs:
|
||||
- lint
|
||||
- test:
|
||||
requires:
|
||||
- lint
|
||||
- build:
|
||||
requires:
|
||||
- test
|
||||
- e2e-test:
|
||||
requires:
|
||||
- build
|
||||
- security-scan:
|
||||
requires:
|
||||
- build
|
||||
- docker-build-and-push:
|
||||
requires:
|
||||
- build
|
||||
- test
|
||||
- security-scan
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- main
|
||||
- develop
|
||||
- deploy-staging:
|
||||
requires:
|
||||
- docker-build-and-push
|
||||
filters:
|
||||
branches:
|
||||
only: develop
|
||||
- hold-for-approval:
|
||||
type: approval
|
||||
requires:
|
||||
- docker-build-and-push
|
||||
- e2e-test
|
||||
filters:
|
||||
branches:
|
||||
only: main
|
||||
- deploy-production:
|
||||
requires:
|
||||
- hold-for-approval
|
||||
filters:
|
||||
branches:
|
||||
only: main
|
||||
20
.dockerignore
Normal file
20
.dockerignore
Normal file
@@ -0,0 +1,20 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
dist
|
||||
.git
|
||||
.github
|
||||
.gitignore
|
||||
.dockerignore
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
*.md
|
||||
coverage
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
playwright-report
|
||||
test-results
|
||||
.vscode
|
||||
.idea
|
||||
*.log
|
||||
.DS_Store
|
||||
241
.github/workflows/ci.yml
vendored
Normal file
241
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
name: CI/CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
NODE_VERSION: '20.x'
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run ESLint
|
||||
run: npm run lint --if-present || echo "No lint script found"
|
||||
|
||||
- name: Type check
|
||||
run: npx tsc --noEmit
|
||||
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run unit tests
|
||||
run: npm test --if-present || echo "No test script found"
|
||||
|
||||
- name: Upload coverage reports
|
||||
uses: codecov/codecov-action@v4
|
||||
if: always()
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./coverage/coverage-final.json
|
||||
flags: unittests
|
||||
fail_ci_if_error: false
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint, test]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build application
|
||||
run: npm run build
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
retention-days: 7
|
||||
|
||||
e2e-tests:
|
||||
name: E2E Tests
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
|
||||
- name: Run E2E tests
|
||||
run: npm run test:e2e --if-present || echo "No E2E tests configured"
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 7
|
||||
|
||||
security-scan:
|
||||
name: Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run npm audit
|
||||
run: npm audit --audit-level=moderate || true
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
scan-ref: '.'
|
||||
format: 'sarif'
|
||||
output: 'trivy-results.sarif'
|
||||
|
||||
- name: Upload Trivy results to GitHub Security
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
if: always()
|
||||
with:
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
|
||||
docker-build:
|
||||
name: Build Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint, test, build]
|
||||
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=sha,prefix={{branch}}-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
deploy-staging:
|
||||
name: Deploy to Staging
|
||||
runs-on: ubuntu-latest
|
||||
needs: [docker-build]
|
||||
if: github.ref == 'refs/heads/develop'
|
||||
environment:
|
||||
name: staging
|
||||
url: https://staging.codeforge.example.com
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Deploy to staging
|
||||
run: |
|
||||
echo "Deploying to staging environment..."
|
||||
echo "Image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:develop-${{ github.sha }}"
|
||||
|
||||
- name: Notify deployment
|
||||
uses: 8398a7/action-slack@v3
|
||||
if: always()
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
text: 'Staging deployment ${{ job.status }}'
|
||||
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
|
||||
|
||||
deploy-production:
|
||||
name: Deploy to Production
|
||||
runs-on: ubuntu-latest
|
||||
needs: [docker-build, e2e-tests]
|
||||
if: github.ref == 'refs/heads/main'
|
||||
environment:
|
||||
name: production
|
||||
url: https://codeforge.example.com
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Deploy to production
|
||||
run: |
|
||||
echo "Deploying to production environment..."
|
||||
echo "Image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-${{ github.sha }}"
|
||||
|
||||
- name: Notify deployment
|
||||
uses: 8398a7/action-slack@v3
|
||||
if: always()
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
text: 'Production deployment ${{ job.status }}'
|
||||
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
|
||||
87
.github/workflows/release.yml
vendored
Normal file
87
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
env:
|
||||
NODE_VERSION: '20.x'
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Create ZIP archive
|
||||
run: |
|
||||
cd dist
|
||||
zip -r ../codeforge-${{ github.ref_name }}.zip .
|
||||
cd ..
|
||||
|
||||
- name: Generate changelog
|
||||
id: changelog
|
||||
run: |
|
||||
echo "## Changes" > CHANGELOG.md
|
||||
git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:"- %s (%h)" >> CHANGELOG.md
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: codeforge-${{ github.ref_name }}.zip
|
||||
body_path: CHANGELOG.md
|
||||
draft: false
|
||||
prerelease: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract version from tag
|
||||
id: version
|
||||
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
labels: |
|
||||
org.opencontainers.image.title=CodeForge
|
||||
org.opencontainers.image.description=Low-Code Next.js App Builder
|
||||
org.opencontainers.image.version=${{ steps.version.outputs.VERSION }}
|
||||
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
177
.gitlab-ci.yml
Normal file
177
.gitlab-ci.yml
Normal file
@@ -0,0 +1,177 @@
|
||||
stages:
|
||||
- lint
|
||||
- test
|
||||
- build
|
||||
- security
|
||||
- docker
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
NODE_VERSION: '20'
|
||||
DOCKER_DRIVER: overlay2
|
||||
DOCKER_TLS_CERTDIR: '/certs'
|
||||
NPM_CONFIG_CACHE: '$CI_PROJECT_DIR/.npm'
|
||||
REGISTRY: '$CI_REGISTRY_IMAGE'
|
||||
|
||||
cache:
|
||||
key:
|
||||
files:
|
||||
- package-lock.json
|
||||
paths:
|
||||
- node_modules/
|
||||
- .npm/
|
||||
|
||||
.node_template: &node_template
|
||||
image: node:${NODE_VERSION}-alpine
|
||||
before_script:
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm ci --cache .npm --prefer-offline
|
||||
|
||||
lint:eslint:
|
||||
<<: *node_template
|
||||
stage: lint
|
||||
script:
|
||||
- npm run lint || echo "No lint script found"
|
||||
allow_failure: false
|
||||
|
||||
lint:typecheck:
|
||||
<<: *node_template
|
||||
stage: lint
|
||||
script:
|
||||
- npx tsc --noEmit
|
||||
allow_failure: false
|
||||
|
||||
test:unit:
|
||||
<<: *node_template
|
||||
stage: test
|
||||
script:
|
||||
- npm test || echo "No test script found"
|
||||
coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
junit: junit.xml
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage/cobertura-coverage.xml
|
||||
paths:
|
||||
- coverage/
|
||||
expire_in: 1 week
|
||||
|
||||
build:app:
|
||||
<<: *node_template
|
||||
stage: build
|
||||
script:
|
||||
- npm run build
|
||||
artifacts:
|
||||
paths:
|
||||
- dist/
|
||||
expire_in: 1 week
|
||||
needs:
|
||||
- lint:eslint
|
||||
- lint:typecheck
|
||||
- test:unit
|
||||
|
||||
test:e2e:
|
||||
image: mcr.microsoft.com/playwright:v1.42.0-focal
|
||||
stage: test
|
||||
script:
|
||||
- npm ci --cache .npm --prefer-offline
|
||||
- npx playwright install chromium
|
||||
- npm run test:e2e || echo "No E2E tests configured"
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- playwright-report/
|
||||
expire_in: 1 week
|
||||
needs:
|
||||
- build:app
|
||||
allow_failure: true
|
||||
|
||||
security:audit:
|
||||
<<: *node_template
|
||||
stage: security
|
||||
script:
|
||||
- npm audit --audit-level=moderate || true
|
||||
allow_failure: true
|
||||
|
||||
security:trivy:
|
||||
stage: security
|
||||
image:
|
||||
name: aquasec/trivy:latest
|
||||
entrypoint: ['']
|
||||
script:
|
||||
- trivy fs --exit-code 0 --no-progress --format json --output trivy-report.json .
|
||||
- trivy fs --exit-code 1 --severity CRITICAL --no-progress .
|
||||
artifacts:
|
||||
reports:
|
||||
container_scanning: trivy-report.json
|
||||
allow_failure: true
|
||||
|
||||
docker:build:
|
||||
stage: docker
|
||||
image: docker:24-dind
|
||||
services:
|
||||
- docker:24-dind
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker build -t $REGISTRY:$CI_COMMIT_REF_SLUG -t $REGISTRY:$CI_COMMIT_SHORT_SHA .
|
||||
- docker push $REGISTRY:$CI_COMMIT_REF_SLUG
|
||||
- docker push $REGISTRY:$CI_COMMIT_SHORT_SHA
|
||||
- |
|
||||
if [ "$CI_COMMIT_REF_NAME" = "main" ]; then
|
||||
docker tag $REGISTRY:$CI_COMMIT_SHORT_SHA $REGISTRY:latest
|
||||
docker push $REGISTRY:latest
|
||||
fi
|
||||
needs:
|
||||
- build:app
|
||||
- test:unit
|
||||
- security:audit
|
||||
only:
|
||||
- main
|
||||
- develop
|
||||
- tags
|
||||
|
||||
deploy:staging:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
before_script:
|
||||
- apk add --no-cache curl
|
||||
script:
|
||||
- echo "Deploying to staging environment..."
|
||||
- echo "Image: $REGISTRY:develop-$CI_COMMIT_SHORT_SHA"
|
||||
- |
|
||||
curl -X POST $STAGING_WEBHOOK_URL \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"image\":\"$REGISTRY:develop\",\"sha\":\"$CI_COMMIT_SHORT_SHA\"}"
|
||||
environment:
|
||||
name: staging
|
||||
url: https://staging.codeforge.example.com
|
||||
needs:
|
||||
- docker:build
|
||||
only:
|
||||
- develop
|
||||
|
||||
deploy:production:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
before_script:
|
||||
- apk add --no-cache curl
|
||||
script:
|
||||
- echo "Deploying to production environment..."
|
||||
- echo "Image: $REGISTRY:main-$CI_COMMIT_SHORT_SHA"
|
||||
- |
|
||||
curl -X POST $PRODUCTION_WEBHOOK_URL \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"image\":\"$REGISTRY:latest\",\"sha\":\"$CI_COMMIT_SHORT_SHA\"}"
|
||||
environment:
|
||||
name: production
|
||||
url: https://codeforge.example.com
|
||||
needs:
|
||||
- docker:build
|
||||
- test:e2e
|
||||
when: manual
|
||||
only:
|
||||
- main
|
||||
350
CI_CD_GUIDE.md
Normal file
350
CI_CD_GUIDE.md
Normal file
@@ -0,0 +1,350 @@
|
||||
# CI/CD Configuration Guide
|
||||
|
||||
This project includes comprehensive CI/CD configurations for multiple platforms. Choose the one that best fits your infrastructure.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [GitHub Actions](#github-actions)
|
||||
- [GitLab CI](#gitlab-ci)
|
||||
- [Jenkins](#jenkins)
|
||||
- [CircleCI](#circleci)
|
||||
- [Docker Setup](#docker-setup)
|
||||
|
||||
---
|
||||
|
||||
## GitHub Actions
|
||||
|
||||
### Location
|
||||
- `.github/workflows/ci.yml` - Main CI/CD pipeline
|
||||
- `.github/workflows/release.yml` - Release automation
|
||||
|
||||
### Features
|
||||
- ✅ Lint and type checking
|
||||
- ✅ Unit and E2E tests
|
||||
- ✅ Docker build and push to GHCR
|
||||
- ✅ Security scanning with Trivy
|
||||
- ✅ Automated deployments to staging/production
|
||||
- ✅ Release creation with ZIP artifacts
|
||||
|
||||
### Setup
|
||||
|
||||
1. **Enable GitHub Actions** in your repository settings
|
||||
|
||||
2. **Configure secrets** (Settings → Secrets and variables → Actions):
|
||||
```
|
||||
CODECOV_TOKEN # Optional: for code coverage reporting
|
||||
SLACK_WEBHOOK # Optional: for Slack notifications
|
||||
STAGING_WEBHOOK_URL # Webhook for staging deployment
|
||||
PRODUCTION_WEBHOOK_URL # Webhook for production deployment
|
||||
```
|
||||
|
||||
3. **Enable GitHub Packages** for Docker image storage (automatically enabled)
|
||||
|
||||
4. **Branch Protection** (recommended):
|
||||
- Require status checks to pass before merging
|
||||
- Require pull request reviews
|
||||
|
||||
### Usage
|
||||
|
||||
- Push to `develop` → Runs tests and deploys to staging
|
||||
- Push to `main` → Runs full pipeline and deploys to production
|
||||
- Create tag `v*` → Triggers release workflow
|
||||
|
||||
---
|
||||
|
||||
## GitLab CI
|
||||
|
||||
### Location
|
||||
- `.gitlab-ci.yml`
|
||||
|
||||
### Features
|
||||
- ✅ Multi-stage pipeline with dependency caching
|
||||
- ✅ Parallel test execution
|
||||
- ✅ Docker build and push to GitLab Registry
|
||||
- ✅ Security scanning and audit reports
|
||||
- ✅ Manual approval for production deployments
|
||||
|
||||
### Setup
|
||||
|
||||
1. **Configure CI/CD variables** (Settings → CI/CD → Variables):
|
||||
```
|
||||
STAGING_WEBHOOK_URL # Webhook for staging deployment
|
||||
PRODUCTION_WEBHOOK_URL # Webhook for production deployment
|
||||
```
|
||||
|
||||
2. **Enable GitLab Container Registry** (enabled by default)
|
||||
|
||||
3. **Configure runners** with Docker executor:
|
||||
```toml
|
||||
[[runners]]
|
||||
name = "docker-runner"
|
||||
executor = "docker"
|
||||
[runners.docker]
|
||||
image = "node:20-alpine"
|
||||
privileged = true
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
- Pipeline runs automatically on push
|
||||
- Jobs are cached for faster execution
|
||||
- Production deployment requires manual approval
|
||||
|
||||
---
|
||||
|
||||
## Jenkins
|
||||
|
||||
### Location
|
||||
- `Jenkinsfile`
|
||||
|
||||
### Features
|
||||
- ✅ Declarative pipeline with parallel stages
|
||||
- ✅ Integration with Slack for notifications
|
||||
- ✅ Artifact archiving and HTML report publishing
|
||||
- ✅ Manual approval for production deployments
|
||||
- ✅ Automatic workspace cleanup
|
||||
|
||||
### Setup
|
||||
|
||||
1. **Install required plugins**:
|
||||
- Pipeline
|
||||
- NodeJS
|
||||
- Docker Pipeline
|
||||
- Slack Notification
|
||||
- HTML Publisher
|
||||
|
||||
2. **Configure Node.js** (Manage Jenkins → Tools):
|
||||
- Add Node.js installation named "Node 20"
|
||||
- Version: 20.x
|
||||
|
||||
3. **Configure credentials**:
|
||||
```
|
||||
docker-registry-credentials # Username/password for GHCR
|
||||
```
|
||||
|
||||
4. **Set environment variables** in Jenkins configuration:
|
||||
```
|
||||
GIT_REPO_OWNER
|
||||
GIT_REPO_NAME
|
||||
STAGING_WEBHOOK_URL
|
||||
PRODUCTION_WEBHOOK_URL
|
||||
SLACK_CHANNEL
|
||||
```
|
||||
|
||||
5. **Create multibranch pipeline**:
|
||||
- New Item → Multibranch Pipeline
|
||||
- Add source: Git/GitHub
|
||||
- Script Path: Jenkinsfile
|
||||
|
||||
### Usage
|
||||
|
||||
- Pipeline triggers on SCM changes (polling or webhooks)
|
||||
- View results in Blue Ocean interface
|
||||
- Approve production deployments manually
|
||||
|
||||
---
|
||||
|
||||
## CircleCI
|
||||
|
||||
### Location
|
||||
- `.circleci/config.yml`
|
||||
|
||||
### Features
|
||||
- ✅ Workflow orchestration with job dependencies
|
||||
- ✅ Docker layer caching for faster builds
|
||||
- ✅ Slack notifications via orb
|
||||
- ✅ Test result and artifact storage
|
||||
- ✅ Approval step for production deployments
|
||||
|
||||
### Setup
|
||||
|
||||
1. **Connect repository** to CircleCI
|
||||
|
||||
2. **Configure environment variables** (Project Settings → Environment Variables):
|
||||
```
|
||||
DOCKER_USERNAME # GitHub username
|
||||
DOCKER_PASSWORD # GitHub personal access token
|
||||
STAGING_WEBHOOK_URL # Webhook for staging deployment
|
||||
PRODUCTION_WEBHOOK_URL # Webhook for production deployment
|
||||
SLACK_ACCESS_TOKEN # Optional: for Slack notifications
|
||||
SLACK_DEFAULT_CHANNEL # Optional: default Slack channel
|
||||
```
|
||||
|
||||
3. **Enable Docker Layer Caching** (requires paid plan):
|
||||
- Project Settings → Advanced → Enable Docker Layer Caching
|
||||
|
||||
### Usage
|
||||
|
||||
- Pipeline runs on every push
|
||||
- Manual approval required for production on `main` branch
|
||||
- View detailed insights in CircleCI dashboard
|
||||
|
||||
---
|
||||
|
||||
## Docker Setup
|
||||
|
||||
### Files
|
||||
- `Dockerfile` - Multi-stage build for production
|
||||
- `docker-compose.yml` - Local development and deployment
|
||||
- `nginx.conf` - Nginx configuration for serving app
|
||||
- `.dockerignore` - Excludes unnecessary files
|
||||
|
||||
### Build and Run Locally
|
||||
|
||||
```bash
|
||||
# Build image
|
||||
docker build -t codeforge:local .
|
||||
|
||||
# Run container
|
||||
docker run -p 3000:80 codeforge:local
|
||||
|
||||
# Or use docker-compose
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Production Deployment
|
||||
|
||||
The Docker image is automatically built and pushed to GHCR:
|
||||
|
||||
```bash
|
||||
# Pull latest image
|
||||
docker pull ghcr.io/<username>/<repo>:latest
|
||||
|
||||
# Run in production
|
||||
docker run -d \
|
||||
-p 80:80 \
|
||||
--name codeforge \
|
||||
--restart unless-stopped \
|
||||
ghcr.io/<username>/<repo>:latest
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
|
||||
The container includes a health check endpoint at `/health`:
|
||||
|
||||
```bash
|
||||
curl http://localhost:3000/health
|
||||
# Response: healthy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
All CI/CD platforms use these common environment variables:
|
||||
|
||||
| Variable | Description | Required |
|
||||
|----------|-------------|----------|
|
||||
| `NODE_VERSION` | Node.js version | Yes (default: 20) |
|
||||
| `REGISTRY` | Docker registry URL | Yes (default: ghcr.io) |
|
||||
| `IMAGE_NAME` | Docker image name | Yes |
|
||||
| `STAGING_WEBHOOK_URL` | Staging deployment webhook | Optional |
|
||||
| `PRODUCTION_WEBHOOK_URL` | Production deployment webhook | Optional |
|
||||
| `CODECOV_TOKEN` | Codecov integration token | Optional |
|
||||
| `SLACK_WEBHOOK` | Slack webhook URL | Optional |
|
||||
|
||||
### Branch Strategy
|
||||
|
||||
- `main` - Production branch, deploys to production
|
||||
- `develop` - Development branch, deploys to staging
|
||||
- `feature/*` - Feature branches, runs tests only
|
||||
- `v*` tags - Triggers release creation
|
||||
|
||||
### Pipeline Stages
|
||||
|
||||
All pipelines follow a similar structure:
|
||||
|
||||
1. **Lint** - ESLint and TypeScript checks
|
||||
2. **Test** - Unit tests with coverage
|
||||
3. **Build** - Application build
|
||||
4. **E2E** - Playwright end-to-end tests
|
||||
5. **Security** - npm audit and Trivy scan
|
||||
6. **Docker** - Build and push image
|
||||
7. **Deploy** - Staging (auto) and Production (manual)
|
||||
|
||||
### Deployment Webhooks
|
||||
|
||||
Configure deployment webhooks to integrate with your hosting platform:
|
||||
|
||||
```bash
|
||||
# Example webhook payload
|
||||
{
|
||||
"image": "ghcr.io/<username>/<repo>:latest",
|
||||
"sha": "abc123",
|
||||
"environment": "production"
|
||||
}
|
||||
```
|
||||
|
||||
Supported platforms:
|
||||
- Vercel
|
||||
- Netlify
|
||||
- AWS ECS/EKS
|
||||
- Kubernetes
|
||||
- Custom deployment scripts
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
**Issue**: Docker push fails
|
||||
```bash
|
||||
Solution: Check GITHUB_TOKEN permissions in repository settings
|
||||
Settings → Actions → General → Workflow permissions → Read and write
|
||||
```
|
||||
|
||||
### GitLab CI
|
||||
|
||||
**Issue**: Runner fails to pull image
|
||||
```bash
|
||||
Solution: Check runner has access to Docker
|
||||
docker info # Should work on runner
|
||||
```
|
||||
|
||||
### Jenkins
|
||||
|
||||
**Issue**: Pipeline hangs on input step
|
||||
```bash
|
||||
Solution: Check Jenkins has sufficient executors
|
||||
Manage Jenkins → Configure System → # of executors
|
||||
```
|
||||
|
||||
### CircleCI
|
||||
|
||||
**Issue**: Build fails with out of memory
|
||||
```bash
|
||||
Solution: Increase resource class in config.yml
|
||||
resource_class: large # or xlarge
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
||||
- [GitLab CI/CD Documentation](https://docs.gitlab.com/ee/ci/)
|
||||
- [Jenkins Pipeline Documentation](https://www.jenkins.io/doc/book/pipeline/)
|
||||
- [CircleCI Documentation](https://circleci.com/docs/)
|
||||
- [Docker Documentation](https://docs.docker.com/)
|
||||
|
||||
---
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Never commit secrets** to the repository
|
||||
2. **Use environment variables** for sensitive data
|
||||
3. **Enable branch protection** on main/develop branches
|
||||
4. **Require code reviews** before merging
|
||||
5. **Run security scans** in every pipeline
|
||||
6. **Keep dependencies updated** using Dependabot/Renovate
|
||||
7. **Use signed commits** for production deployments
|
||||
8. **Implement RBAC** for deployment approvals
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
This CI/CD configuration is part of CodeForge and follows the same license as the main project.
|
||||
24
Dockerfile
Normal file
24
Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
|
||||
RUN npm ci --only=production
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN npm run build
|
||||
|
||||
FROM nginx:alpine AS runtime
|
||||
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD wget --quiet --tries=1 --spider http://localhost/health || exit 1
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
291
Jenkinsfile
vendored
Normal file
291
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
NODE_VERSION = '20'
|
||||
REGISTRY = 'ghcr.io'
|
||||
IMAGE_NAME = "${env.REGISTRY}/${env.GIT_REPO_OWNER}/${env.GIT_REPO_NAME}"
|
||||
DOCKER_CREDENTIALS = credentials('docker-registry-credentials')
|
||||
SLACK_CHANNEL = '#deployments'
|
||||
}
|
||||
|
||||
options {
|
||||
buildDiscarder(logRotator(numToKeepStr: '10'))
|
||||
disableConcurrentBuilds()
|
||||
timeout(time: 1, unit: 'HOURS')
|
||||
timestamps()
|
||||
}
|
||||
|
||||
triggers {
|
||||
pollSCM('H/5 * * * *')
|
||||
githubPush()
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
checkout scm
|
||||
script {
|
||||
env.GIT_COMMIT_SHORT = sh(
|
||||
script: "git rev-parse --short HEAD",
|
||||
returnStdout: true
|
||||
).trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Setup') {
|
||||
steps {
|
||||
script {
|
||||
nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
|
||||
sh '''
|
||||
node --version
|
||||
npm --version
|
||||
npm ci
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Lint') {
|
||||
parallel {
|
||||
stage('ESLint') {
|
||||
steps {
|
||||
script {
|
||||
nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
|
||||
sh 'npm run lint || echo "No lint script found"'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('TypeScript Check') {
|
||||
steps {
|
||||
script {
|
||||
nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
|
||||
sh 'npx tsc --noEmit'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Test') {
|
||||
steps {
|
||||
script {
|
||||
nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
|
||||
sh 'npm test || echo "No test script found"'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit testResults: '**/junit.xml', allowEmptyResults: true
|
||||
publishHTML([
|
||||
allowMissing: true,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: 'coverage',
|
||||
reportFiles: 'index.html',
|
||||
reportName: 'Coverage Report'
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
steps {
|
||||
script {
|
||||
nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
|
||||
sh 'npm run build'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
archiveArtifacts artifacts: 'dist/**/*', fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('E2E Tests') {
|
||||
when {
|
||||
anyOf {
|
||||
branch 'main'
|
||||
branch 'develop'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
|
||||
sh '''
|
||||
npx playwright install --with-deps chromium
|
||||
npm run test:e2e || echo "No E2E tests configured"
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
publishHTML([
|
||||
allowMissing: true,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: 'playwright-report',
|
||||
reportFiles: 'index.html',
|
||||
reportName: 'Playwright Report'
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Security Scan') {
|
||||
parallel {
|
||||
stage('NPM Audit') {
|
||||
steps {
|
||||
script {
|
||||
nodejs(nodeJSInstallationName: "Node ${NODE_VERSION}") {
|
||||
sh 'npm audit --audit-level=moderate || true'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Trivy Scan') {
|
||||
steps {
|
||||
sh '''
|
||||
docker run --rm -v $(pwd):/workspace aquasec/trivy:latest \
|
||||
fs --exit-code 0 --no-progress --format json \
|
||||
--output /workspace/trivy-report.json /workspace
|
||||
'''
|
||||
}
|
||||
post {
|
||||
always {
|
||||
archiveArtifacts artifacts: 'trivy-report.json', allowEmptyArchive: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Docker Build') {
|
||||
when {
|
||||
anyOf {
|
||||
branch 'main'
|
||||
branch 'develop'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
def imageTags = [
|
||||
"${IMAGE_NAME}:${env.BRANCH_NAME}",
|
||||
"${IMAGE_NAME}:${env.BRANCH_NAME}-${env.GIT_COMMIT_SHORT}"
|
||||
]
|
||||
|
||||
if (env.BRANCH_NAME == 'main') {
|
||||
imageTags.add("${IMAGE_NAME}:latest")
|
||||
}
|
||||
|
||||
docker.withRegistry("https://${REGISTRY}", 'docker-registry-credentials') {
|
||||
def customImage = docker.build("${IMAGE_NAME}:${env.BUILD_ID}")
|
||||
imageTags.each { tag ->
|
||||
customImage.push(tag.split(':')[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Deploy to Staging') {
|
||||
when {
|
||||
branch 'develop'
|
||||
}
|
||||
environment {
|
||||
DEPLOY_ENV = 'staging'
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
echo "Deploying to staging environment..."
|
||||
echo "Image: ${IMAGE_NAME}:develop-${env.GIT_COMMIT_SHORT}"
|
||||
|
||||
sh '''
|
||||
curl -X POST ${STAGING_WEBHOOK_URL} \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\\"image\\":\\"${IMAGE_NAME}:develop\\",\\"sha\\":\\"${GIT_COMMIT_SHORT}\\"}"
|
||||
'''
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
slackSend(
|
||||
channel: SLACK_CHANNEL,
|
||||
color: 'good',
|
||||
message: "Staging deployment successful: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
|
||||
)
|
||||
}
|
||||
failure {
|
||||
slackSend(
|
||||
channel: SLACK_CHANNEL,
|
||||
color: 'danger',
|
||||
message: "Staging deployment failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Deploy to Production') {
|
||||
when {
|
||||
branch 'main'
|
||||
}
|
||||
environment {
|
||||
DEPLOY_ENV = 'production'
|
||||
}
|
||||
steps {
|
||||
input message: 'Deploy to production?', ok: 'Deploy'
|
||||
script {
|
||||
echo "Deploying to production environment..."
|
||||
echo "Image: ${IMAGE_NAME}:latest"
|
||||
|
||||
sh '''
|
||||
curl -X POST ${PRODUCTION_WEBHOOK_URL} \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\\"image\\":\\"${IMAGE_NAME}:latest\\",\\"sha\\":\\"${GIT_COMMIT_SHORT}\\"}"
|
||||
'''
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
slackSend(
|
||||
channel: SLACK_CHANNEL,
|
||||
color: 'good',
|
||||
message: "Production deployment successful: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
|
||||
)
|
||||
}
|
||||
failure {
|
||||
slackSend(
|
||||
channel: SLACK_CHANNEL,
|
||||
color: 'danger',
|
||||
message: "Production deployment failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
echo 'Pipeline completed successfully!'
|
||||
}
|
||||
failure {
|
||||
echo 'Pipeline failed!'
|
||||
slackSend(
|
||||
channel: SLACK_CHANNEL,
|
||||
color: 'danger',
|
||||
message: "Build failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
13
README.md
13
README.md
@@ -86,6 +86,7 @@ The application includes comprehensive built-in documentation:
|
||||
- **Roadmap** - Completed features and planned enhancements
|
||||
- **Agents Files** - AI service architecture and integration points
|
||||
- **Sass Styles Guide** - Custom Material UI components, utilities, mixins, and animations
|
||||
- **CI/CD Guide** - Complete setup guide for all CI/CD platforms
|
||||
|
||||
Access documentation by clicking the **Documentation** tab in the application.
|
||||
|
||||
@@ -105,16 +106,23 @@ Access documentation by clicking the **Documentation** tab in the application.
|
||||
- ZIP file export with README generation
|
||||
- Keyboard shortcuts for power users
|
||||
|
||||
### ✅ Recently Added (v4.2)
|
||||
- Complete CI/CD configurations (GitHub Actions, GitLab CI, Jenkins, CircleCI)
|
||||
- Docker containerization with multi-stage builds
|
||||
- Nginx configuration for production deployment
|
||||
- Automated release workflow with versioning
|
||||
- Security scanning integration (Trivy, npm audit)
|
||||
- Slack notification integration
|
||||
- Health check endpoints
|
||||
|
||||
### 🔮 Planned
|
||||
- Real-time preview with hot reload
|
||||
- Database seeding designer
|
||||
- API client generator
|
||||
- Visual form builder
|
||||
- Authentication designer (JWT, OAuth, sessions)
|
||||
- Docker configuration generator
|
||||
- GraphQL API designer
|
||||
- State management designer (Redux, Zustand, Jotai)
|
||||
- CI/CD pipeline generator
|
||||
- Component library export
|
||||
- Design system generator
|
||||
- Collaboration features
|
||||
@@ -138,6 +146,7 @@ The Spark Template files and resources from GitHub are licensed under the terms
|
||||
|
||||
- [Full Documentation](./PRD.md) - Complete product requirements and design decisions
|
||||
- [Error Repair Guide](./ERROR_REPAIR_GUIDE.md) - Error detection and repair system documentation
|
||||
- [CI/CD Guide](./CI_CD_GUIDE.md) - Complete CI/CD setup and configuration guide
|
||||
|
||||
---
|
||||
|
||||
|
||||
26
docker-compose.yml
Normal file
26
docker-compose.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- '3000:80'
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost/health']
|
||||
interval: 30s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
start_period: 5s
|
||||
labels:
|
||||
- 'traefik.enable=true'
|
||||
- 'traefik.http.routers.codeforge.rule=Host(`codeforge.example.com`)'
|
||||
- 'traefik.http.services.codeforge.loadbalancer.server.port=80'
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: codeforge-network
|
||||
28
nginx.conf
Normal file
28
nginx.conf
Normal file
@@ -0,0 +1,28 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
|
||||
|
||||
error_page 404 /index.html;
|
||||
}
|
||||
@@ -25,7 +25,8 @@ import {
|
||||
Rocket,
|
||||
Target,
|
||||
Lightbulb,
|
||||
MagnifyingGlass
|
||||
MagnifyingGlass,
|
||||
GitBranch
|
||||
} from '@phosphor-icons/react'
|
||||
|
||||
export function DocumentationView() {
|
||||
@@ -54,6 +55,10 @@ export function DocumentationView() {
|
||||
<PaintBrush size={18} />
|
||||
Sass Styles Guide
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="cicd" className="gap-2">
|
||||
<GitBranch size={18} />
|
||||
CI/CD Guide
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</div>
|
||||
<div className="relative">
|
||||
@@ -433,6 +438,18 @@ export function DocumentationView() {
|
||||
description="Next.js configuration, npm package management, and build script customization"
|
||||
version="v4.0"
|
||||
/>
|
||||
<RoadmapItem
|
||||
status="completed"
|
||||
title="CI/CD Configuration"
|
||||
description="Complete CI/CD pipelines for GitHub Actions, GitLab CI, Jenkins, and CircleCI"
|
||||
version="v4.2"
|
||||
/>
|
||||
<RoadmapItem
|
||||
status="completed"
|
||||
title="Docker Containerization"
|
||||
description="Multi-stage Docker builds with Nginx, docker-compose, and health checks"
|
||||
version="v4.2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1127,6 +1144,450 @@ function MyComponent() {
|
||||
</Card>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="cicd" className="m-0 space-y-6">
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-16 h-16 rounded-xl bg-gradient-to-br from-primary to-accent flex items-center justify-center">
|
||||
<GitBranch size={32} weight="duotone" className="text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-4xl font-bold">CI/CD Guide</h1>
|
||||
<p className="text-lg text-muted-foreground">
|
||||
Complete deployment automation for multiple platforms
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-2xl font-semibold">Overview</h2>
|
||||
<p className="text-foreground/90 leading-relaxed">
|
||||
CodeForge includes production-ready CI/CD configurations for GitHub Actions, GitLab CI, Jenkins,
|
||||
and CircleCI. Each pipeline includes linting, testing, security scanning, Docker image building,
|
||||
and automated deployment workflows.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Available Configurations</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<CICDPlatformItem
|
||||
name="GitHub Actions"
|
||||
file=".github/workflows/ci.yml"
|
||||
description="Complete CI/CD with GHCR Docker registry integration"
|
||||
features={[
|
||||
'Parallel lint and test execution',
|
||||
'E2E tests with Playwright',
|
||||
'Docker build and push to GitHub Container Registry',
|
||||
'Security scanning with Trivy',
|
||||
'Automated staging and production deployments',
|
||||
'Release workflow with versioned artifacts'
|
||||
]}
|
||||
/>
|
||||
<CICDPlatformItem
|
||||
name="GitLab CI"
|
||||
file=".gitlab-ci.yml"
|
||||
description="Multi-stage pipeline with GitLab Container Registry"
|
||||
features={[
|
||||
'Dependency caching for faster builds',
|
||||
'Coverage reporting with Cobertura',
|
||||
'Docker-in-Docker builds',
|
||||
'Manual production approval gates',
|
||||
'Webhook-based deployment triggers'
|
||||
]}
|
||||
/>
|
||||
<CICDPlatformItem
|
||||
name="Jenkins"
|
||||
file="Jenkinsfile"
|
||||
description="Declarative pipeline with Slack notifications"
|
||||
features={[
|
||||
'Node.js environment configuration',
|
||||
'HTML report publishing for tests and coverage',
|
||||
'Artifact archiving and fingerprinting',
|
||||
'Manual production deployment approval',
|
||||
'Slack integration for deployment notifications'
|
||||
]}
|
||||
/>
|
||||
<CICDPlatformItem
|
||||
name="CircleCI"
|
||||
file=".circleci/config.yml"
|
||||
description="Workflow orchestration with orb integrations"
|
||||
features={[
|
||||
'Docker layer caching for optimization',
|
||||
'Job dependency management',
|
||||
'Test results and artifact storage',
|
||||
'Approval workflows for production',
|
||||
'Slack notifications via orb'
|
||||
]}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-2xl font-semibold">Pipeline Stages</h2>
|
||||
<p className="text-foreground/90 leading-relaxed">
|
||||
All CI/CD configurations follow a similar multi-stage pipeline structure:
|
||||
</p>
|
||||
<div className="grid gap-3">
|
||||
<PipelineStageCard
|
||||
stage="Lint"
|
||||
description="ESLint and TypeScript type checking to ensure code quality"
|
||||
duration="~1-2 min"
|
||||
/>
|
||||
<PipelineStageCard
|
||||
stage="Test"
|
||||
description="Unit tests with coverage reporting and result artifacts"
|
||||
duration="~2-3 min"
|
||||
/>
|
||||
<PipelineStageCard
|
||||
stage="Build"
|
||||
description="Production build with artifact generation for deployment"
|
||||
duration="~2-4 min"
|
||||
/>
|
||||
<PipelineStageCard
|
||||
stage="E2E Tests"
|
||||
description="Playwright end-to-end tests with HTML reports"
|
||||
duration="~3-5 min"
|
||||
/>
|
||||
<PipelineStageCard
|
||||
stage="Security"
|
||||
description="npm audit and Trivy vulnerability scanning"
|
||||
duration="~1-2 min"
|
||||
/>
|
||||
<PipelineStageCard
|
||||
stage="Docker Build"
|
||||
description="Multi-stage Docker image build and push to registry"
|
||||
duration="~3-5 min"
|
||||
/>
|
||||
<PipelineStageCard
|
||||
stage="Deploy"
|
||||
description="Automated deployment to staging and production environments"
|
||||
duration="~1-3 min"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Docker Configuration</CardTitle>
|
||||
<CardDescription>Containerization for production deployment</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<h3 className="font-semibold">Files Included</h3>
|
||||
<div className="space-y-2 ml-4">
|
||||
<div className="space-y-1">
|
||||
<code className="text-sm font-mono text-accent">Dockerfile</code>
|
||||
<p className="text-sm text-muted-foreground">Multi-stage build with Node.js builder and Nginx runtime</p>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<code className="text-sm font-mono text-accent">nginx.conf</code>
|
||||
<p className="text-sm text-muted-foreground">Production Nginx configuration with health checks and caching</p>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<code className="text-sm font-mono text-accent">docker-compose.yml</code>
|
||||
<p className="text-sm text-muted-foreground">Local development and deployment orchestration</p>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<code className="text-sm font-mono text-accent">.dockerignore</code>
|
||||
<p className="text-sm text-muted-foreground">Optimized build context by excluding unnecessary files</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-2">
|
||||
<h3 className="font-semibold">Docker Commands</h3>
|
||||
<pre className="custom-mui-code-block">
|
||||
{`# Build image locally
|
||||
docker build -t codeforge:local .
|
||||
|
||||
# Run container
|
||||
docker run -p 3000:80 codeforge:local
|
||||
|
||||
# Use docker-compose
|
||||
docker-compose up -d
|
||||
|
||||
# Pull from registry
|
||||
docker pull ghcr.io/<username>/<repo>:latest`}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-2">
|
||||
<h3 className="font-semibold">Features</h3>
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Multi-stage build reduces final image size to ~50MB</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Nginx serves static files with gzip compression</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Health check endpoint at /health for orchestration</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Automatic cache headers for static assets</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>SPA routing support with fallback to index.html</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Environment Variables</CardTitle>
|
||||
<CardDescription>Required configuration for CI/CD platforms</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="border-b">
|
||||
<th className="text-left py-2 pr-4 font-semibold">Variable</th>
|
||||
<th className="text-left py-2 pr-4 font-semibold">Description</th>
|
||||
<th className="text-left py-2 font-semibold">Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-muted-foreground">
|
||||
<tr className="border-b">
|
||||
<td className="py-2 pr-4"><code className="text-accent">NODE_VERSION</code></td>
|
||||
<td className="py-2 pr-4">Node.js version (default: 20)</td>
|
||||
<td className="py-2">No</td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="py-2 pr-4"><code className="text-accent">REGISTRY</code></td>
|
||||
<td className="py-2 pr-4">Docker registry URL (default: ghcr.io)</td>
|
||||
<td className="py-2">No</td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="py-2 pr-4"><code className="text-accent">STAGING_WEBHOOK_URL</code></td>
|
||||
<td className="py-2 pr-4">Webhook for staging deployments</td>
|
||||
<td className="py-2">Optional</td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="py-2 pr-4"><code className="text-accent">PRODUCTION_WEBHOOK_URL</code></td>
|
||||
<td className="py-2 pr-4">Webhook for production deployments</td>
|
||||
<td className="py-2">Optional</td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="py-2 pr-4"><code className="text-accent">CODECOV_TOKEN</code></td>
|
||||
<td className="py-2 pr-4">Codecov integration token</td>
|
||||
<td className="py-2">Optional</td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="py-2 pr-4"><code className="text-accent">SLACK_WEBHOOK</code></td>
|
||||
<td className="py-2 pr-4">Slack webhook for notifications</td>
|
||||
<td className="py-2">Optional</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-2xl font-semibold">Branch Strategy</h2>
|
||||
<div className="grid gap-4">
|
||||
<Card className="bg-green-500/5 border-green-500/20">
|
||||
<CardContent className="pt-4 pb-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<GitBranch size={20} weight="duotone" className="text-green-500 mt-0.5" />
|
||||
<div className="space-y-1">
|
||||
<h4 className="font-semibold">main</h4>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Production branch - deploys to production environment (manual approval required)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="bg-blue-500/5 border-blue-500/20">
|
||||
<CardContent className="pt-4 pb-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<GitBranch size={20} weight="duotone" className="text-blue-500 mt-0.5" />
|
||||
<div className="space-y-1">
|
||||
<h4 className="font-semibold">develop</h4>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Development branch - automatically deploys to staging environment
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="bg-purple-500/5 border-purple-500/20">
|
||||
<CardContent className="pt-4 pb-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<GitBranch size={20} weight="duotone" className="text-purple-500 mt-0.5" />
|
||||
<div className="space-y-1">
|
||||
<h4 className="font-semibold">feature/*</h4>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Feature branches - runs tests only, no deployment
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="bg-orange-500/5 border-orange-500/20">
|
||||
<CardContent className="pt-4 pb-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<GitBranch size={20} weight="duotone" className="text-orange-500 mt-0.5" />
|
||||
<div className="space-y-1">
|
||||
<h4 className="font-semibold">v* tags</h4>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Version tags - triggers release workflow with artifacts and changelog
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Card className="bg-accent/10 border-accent/20">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Lightbulb size={20} weight="duotone" className="text-accent" />
|
||||
Quick Start
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-2">
|
||||
<h3 className="font-semibold flex items-center gap-2">
|
||||
<span className="w-6 h-6 rounded-full bg-accent text-accent-foreground flex items-center justify-center text-sm">1</span>
|
||||
Choose Your Platform
|
||||
</h3>
|
||||
<p className="text-sm text-foreground/80 ml-8">
|
||||
Select GitHub Actions, GitLab CI, Jenkins, or CircleCI based on your infrastructure
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h3 className="font-semibold flex items-center gap-2">
|
||||
<span className="w-6 h-6 rounded-full bg-accent text-accent-foreground flex items-center justify-center text-sm">2</span>
|
||||
Configure Secrets
|
||||
</h3>
|
||||
<p className="text-sm text-foreground/80 ml-8">
|
||||
Add required environment variables and secrets in your platform's settings
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h3 className="font-semibold flex items-center gap-2">
|
||||
<span className="w-6 h-6 rounded-full bg-accent text-accent-foreground flex items-center justify-center text-sm">3</span>
|
||||
Push to Repository
|
||||
</h3>
|
||||
<p className="text-sm text-foreground/80 ml-8">
|
||||
Push code to main or develop branch to trigger the CI/CD pipeline
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h3 className="font-semibold flex items-center gap-2">
|
||||
<span className="w-6 h-6 rounded-full bg-accent text-accent-foreground flex items-center justify-center text-sm">4</span>
|
||||
Monitor Pipeline
|
||||
</h3>
|
||||
<p className="text-sm text-foreground/80 ml-8">
|
||||
View pipeline status, test results, and deployment logs in your platform's dashboard
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-muted/50">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Rocket size={20} weight="duotone" />
|
||||
Best Practices
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Never commit secrets - use environment variables and platform secret management</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Enable branch protection on main and develop branches</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Require code reviews and passing tests before merging</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Use manual approval gates for production deployments</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Monitor security scan results and fix vulnerabilities promptly</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Keep dependencies updated with Dependabot or Renovate</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Use semantic versioning for releases (v1.0.0, v1.1.0, etc.)</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle size={16} className="text-accent mt-1 flex-shrink-0" weight="fill" />
|
||||
<span>Configure Slack or email notifications for deployment status</span>
|
||||
</li>
|
||||
</ul>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-primary/30">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Package size={20} weight="duotone" />
|
||||
Additional Resources
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li className="flex items-start gap-2">
|
||||
<FileCode size={16} className="text-accent mt-1 flex-shrink-0" />
|
||||
<span><code className="text-accent">CI_CD_GUIDE.md</code> - Detailed setup guide for all platforms</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<FileCode size={16} className="text-accent mt-1 flex-shrink-0" />
|
||||
<span><code className="text-accent">.github/workflows/</code> - GitHub Actions workflows</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<FileCode size={16} className="text-accent mt-1 flex-shrink-0" />
|
||||
<span><code className="text-accent">.gitlab-ci.yml</code> - GitLab CI configuration</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<FileCode size={16} className="text-accent mt-1 flex-shrink-0" />
|
||||
<span><code className="text-accent">Jenkinsfile</code> - Jenkins pipeline definition</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<FileCode size={16} className="text-accent mt-1 flex-shrink-0" />
|
||||
<span><code className="text-accent">.circleci/config.yml</code> - CircleCI configuration</span>
|
||||
</li>
|
||||
</ul>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</div>
|
||||
</ScrollArea>
|
||||
</Tabs>
|
||||
@@ -1134,6 +1595,59 @@ function MyComponent() {
|
||||
)
|
||||
}
|
||||
|
||||
function CICDPlatformItem({ name, file, description, features }: {
|
||||
name: string
|
||||
file: string
|
||||
description: string
|
||||
features: string[]
|
||||
}) {
|
||||
return (
|
||||
<div className="space-y-3 border-l-2 border-accent pl-4">
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<GitBranch size={18} className="text-accent" />
|
||||
<h3 className="text-base font-semibold">{name}</h3>
|
||||
</div>
|
||||
<code className="text-xs text-muted-foreground font-mono">{file}</code>
|
||||
<p className="text-sm text-foreground/90">{description}</p>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">Key Features:</p>
|
||||
<ul className="space-y-1">
|
||||
{features.map((feature, idx) => (
|
||||
<li key={idx} className="text-sm text-foreground/80 flex items-start gap-2">
|
||||
<CheckCircle size={14} weight="fill" className="text-accent mt-1 flex-shrink-0" />
|
||||
<span>{feature}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function PipelineStageCard({ stage, description, duration }: {
|
||||
stage: string
|
||||
description: string
|
||||
duration: string
|
||||
}) {
|
||||
return (
|
||||
<Card className="bg-primary/5 border-primary/20">
|
||||
<CardContent className="pt-4 pb-4">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="space-y-1 flex-1">
|
||||
<h4 className="font-semibold text-sm">{stage}</h4>
|
||||
<p className="text-sm text-muted-foreground">{description}</p>
|
||||
</div>
|
||||
<Badge variant="secondary" className="text-xs whitespace-nowrap">
|
||||
{duration}
|
||||
</Badge>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
function SassComponentItem({ name, classes, description }: { name: string; classes: string[]; description: string }) {
|
||||
return (
|
||||
<div className="space-y-2 p-4 border rounded-lg bg-card">
|
||||
|
||||
Reference in New Issue
Block a user