Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/initial-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@ciscode/ui-chart-kit': minor
---

Initial release of @ciscode/ui-chart-kit v0.1.0.

- ChartDataPoint, ChartDataset, and ChartTheme type contracts
- buildChartConfig utility mapping typed data to Chart.js config
- BarChart component with stacked and horizontal support
- LineChart component with smooth curve support
- AreaChart component with fill at 20% opacity and stacked support
- All components responsive with configurable height
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @CISCODE-MA/devops
20 changes: 20 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: 2
updates:
- package-ecosystem: npm
directory: '/'
schedule:
interval: monthly
open-pull-requests-limit: 1
groups:
npm-dependencies:
patterns:
- '*'
assignees:
- CISCODE-MA/cloud-devops
labels:
- 'dependencies'
- 'npm'
commit-message:
prefix: 'chore(deps)'
include: 'scope'
rebase-strategy: auto
41 changes: 41 additions & 0 deletions .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI - PR Validation

on:
pull_request:
branches: [develop]

permissions:
contents: read

jobs:
validate:
name: CI - PR Validation
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- name: Install
run: npm ci

- name: Format (check)
run: npm run format

- name: Lint
run: npm run lint

- name: Typecheck
run: npm run typecheck

- name: Test
run: npm test

- name: Build
run: npm run build
44 changes: 33 additions & 11 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,52 @@ jobs:
with:
fetch-depth: 0

- name: Validate tag exists on this push
- name: Validate version tag and package.json
run: |
TAG=$(git describe --exact-match --tags HEAD 2>/dev/null || echo "")
if [[ -z "$TAG" ]]; then
echo "❌ No tag found on HEAD. This push did not include a version tag."
echo "To publish, merge to master with a tag: git tag v1.0.0 && git push origin master --tags"
PKG_VERSION=$(grep '"version"' package.json | head -1 | sed 's/.*"version": "\([^"]*\)".*/\1/')
TAG="v${PKG_VERSION}"

if [[ -z "$PKG_VERSION" ]]; then
echo "❌ ERROR: Could not read version from package.json"
exit 1
fi

if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "❌ Invalid tag format: $TAG. Expected: v*.*.*"
echo "❌ ERROR: Invalid version format in package.json: '$PKG_VERSION'"
echo "Expected format: x.y.z (e.g., 1.0.0, 0.2.3)"
exit 1
fi

if ! git rev-parse "$TAG" >/dev/null 2>&1; then
echo "❌ ERROR: Tag $TAG not found!"
echo ""
echo "This typically happens when:"
echo " 1. You forgot to run 'npm version patch|minor|major' on your feature branch"
echo " 2. You didn't push the tag: git push origin <feat/your-feature> --tags"
echo " 3. The tag was created locally but never pushed to remote"
echo ""
echo "📋 Correct workflow:"
echo " 1. On feat/** or feature/**: npm version patch (or minor/major)"
echo " 2. Push branch + tag: git push origin feat/your-feature --tags"
echo " 3. PR feat/** → develop, then PR develop → master"
echo " 4. Workflow automatically triggers on master push"
echo ""
exit 1
fi
echo "✅ Valid tag found: $TAG"

echo "✅ package.json version: $PKG_VERSION"
echo "✅ Tag $TAG exists in repo"
echo "TAG_VERSION=$TAG" >> $GITHUB_ENV

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'
registry-url: 'https://registry.npmjs.org'
cache: npm
cache: 'npm'

- name: Install dependencies
run: npm install
run: npm ci

- name: Build
run: npm run build --if-present
Expand All @@ -55,6 +77,6 @@ jobs:
run: npm test --if-present 2>/dev/null || true

- name: Publish to NPM
run: npm publish --access public --no-git-checks
run: npm publish --access public --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
185 changes: 147 additions & 38 deletions .github/workflows/release-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,43 @@ name: CI - Release Check
on:
pull_request:
branches: [master]
workflow_dispatch:
inputs:
sonar:
description: 'Run SonarCloud analysis'
required: true
default: 'false'
type: choice
options:
- 'false'
- 'true'

concurrency:
group: ci-release-${{ github.ref }}
cancel-in-progress: true

env:
SONAR_HOST_URL: 'https://sonarcloud.io'
SONAR_ORGANIZATION: 'ciscode'
SONAR_PROJECT_KEY: 'CISCODE-MA_ChartKit-UI'
NODE_VERSION: '22'

# ─── Job 1: Static checks (fast feedback, runs in parallel with test) ──────────
jobs:
ci:
name: release checks
quality:
name: Quality Checks
runs-on: ubuntu-latest
timeout-minutes: 25
timeout-minutes: 10

permissions:
contents: read

# Update these values for your package:
# - SONAR_PROJECT_KEY: "CISCODE-MA_YourPackageName"
env:
SONAR_HOST_URL: 'https://sonarcloud.io'
SONAR_ORGANIZATION: 'ciscode'
SONAR_PROJECT_KEY: 'CISCODE-MA_PACKAGE_NAME_TEMPLATE'

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: npm
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install
run: npm install
run: npm ci

- name: Audit
run: npm audit --prod
- name: Security Audit
# Only fail on high/critical — moderate noise in dev deps is expected
run: npm audit --production --audit-level=high

- name: Format
run: npm run format
Expand All @@ -61,29 +50,149 @@ jobs:
- name: Lint
run: npm run lint

# ─── Job 2: Tests + Coverage (artifact passed to Sonar) ────────────────────────
test:
name: Test & Coverage
runs-on: ubuntu-latest
timeout-minutes: 15

permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install
run: npm ci

- name: Test (with coverage)
run: npm run test:cov

- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
retention-days: 1

# ─── Job 3: Build ──────────────────────────────────────────────────────────────
build:
name: Build
runs-on: ubuntu-latest
needs: [quality, test]
timeout-minutes: 10

permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install
run: npm ci

- name: Build
run: npm run build

# ─── Job 4: SonarCloud (depends on test for coverage data) ─────────────────────
sonar:
name: SonarCloud Analysis
runs-on: ubuntu-latest
needs: [test]
timeout-minutes: 15

permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Full history required for accurate blame & new code detection
fetch-depth: 0

- name: Download coverage report
uses: actions/download-artifact@v4
with:
name: coverage-report
path: coverage/

- name: Cache SonarCloud packages
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: sonar-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: sonar-${{ runner.os }}-

- name: SonarCloud Scan
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.sonar == 'true' }}
uses: SonarSource/sonarqube-scan-action@v6
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ env.SONAR_HOST_URL }}
with:
args: >
-Dsonar.organization=${{ env.SONAR_ORGANIZATION }} \
-Dsonar.projectKey=${{ env.SONAR_PROJECT_KEY }} \
-Dsonar.sources=src \
-Dsonar.organization=${{ env.SONAR_ORGANIZATION }}
-Dsonar.projectKey=${{ env.SONAR_PROJECT_KEY }}
-Dsonar.sources=src
-Dsonar.tests=test
-Dsonar.test.inclusions=**/*.spec.ts,**/*.test.ts
-Dsonar.exclusions=**/node_modules/**,**/dist/**,**/coverage/**,**/*.d.ts
-Dsonar.coverage.exclusions=**/*.spec.ts,**/*.test.ts,**/index.ts
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
-Dsonar.typescript.tsconfigPath=tsconfig.json
-Dsonar.qualitygate.wait=true
-Dsonar.qualitygate.timeout=300

- name: SonarCloud Quality Gate
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.sonar == 'true' }}
uses: SonarSource/sonarqube-quality-gate-action@v1
timeout-minutes: 10
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ env.SONAR_HOST_URL }}
# ─── Job 5: Final status report (always runs) ──────────────────────────────────
report:
name: Report CI Status
runs-on: ubuntu-latest
needs: [quality, test, build, sonar]
# Run even if upstream jobs failed
if: always()
timeout-minutes: 5

permissions:
contents: read
statuses: write

steps:
- name: Resolve overall result
id: result
run: |
results="${{ needs.quality.result }} ${{ needs.test.result }} ${{ needs.build.result }} ${{ needs.sonar.result }}"
if echo "$results" | grep -qE "failure|cancelled"; then
echo "state=failure" >> $GITHUB_OUTPUT
echo "desc=One or more CI checks failed" >> $GITHUB_OUTPUT
else
echo "state=success" >> $GITHUB_OUTPUT
echo "desc=All CI checks passed" >> $GITHUB_OUTPUT
fi

- name: Post commit status
uses: actions/github-script@v7
with:
script: |
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: context.sha,
state: '${{ steps.result.outputs.state }}',
context: 'CI / Release Check',
description: '${{ steps.result.outputs.desc }}',
target_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`
})
8 changes: 8 additions & 0 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"servers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"]
}
}
}
Loading
Loading