Skip to content
Merged
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
11 changes: 11 additions & 0 deletions .changeset/release-v0.1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@ciscode/api-kit': minor
---

Initial release of @ciscode/api-kit v0.1.0

- `createApiClient` factory with typed `get`, `post`, `put`, `patch`, `delete` methods
- Built-in auth token injection via `getToken` config
- Composable request, response, and error interceptors
- `ApiError` class normalizing all HTTP/network errors
- Configurable retry with exponential backoff
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/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
54 changes: 43 additions & 11 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,62 @@ 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
Comment on lines +23 to 54
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The publish workflow now only checks that the computed version tag exists somewhere in the repo, not that it points to the commit being built. This can allow publishing from an untagged HEAD (or a HEAD whose package.json version matches an older tag). Validate that TAG resolves to HEAD (or that HEAD is exactly tagged) before proceeding.

Copilot uses AI. Check for mistakes.
echo "✅ Valid tag found: $TAG"

TAG_COMMIT=$(git rev-list -n 1 "$TAG" 2>/dev/null || echo "")
HEAD_COMMIT=$(git rev-parse HEAD)

if [[ "$TAG_COMMIT" != "$HEAD_COMMIT" ]]; then
echo "❌ ERROR: Tag $TAG does not point to HEAD"
echo " Tag points to: $TAG_COMMIT"
echo " HEAD is: $HEAD_COMMIT"
exit 1
fi

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 +87,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 }}
38 changes: 13 additions & 25 deletions .github/workflows/release-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@ 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 }}
Expand All @@ -24,15 +14,11 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 25

permissions:
contents: read

# Update these values for your package:
# - SONAR_PROJECT_KEY: "CISCODE-MA_YourPackageName"
# Config stays in the workflow file (token stays in repo secrets)
env:
SONAR_HOST_URL: 'https://sonarcloud.io'
SONAR_ORGANIZATION: 'ciscode'
SONAR_PROJECT_KEY: 'CISCODE-MA_PACKAGE_NAME_TEMPLATE'
SONAR_PROJECT_KEY: 'CISCODE-MA_ApiKit'

steps:
- name: Checkout
Expand All @@ -43,14 +29,14 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: npm
node-version: '22'
cache: 'npm'

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

- name: Audit
run: npm audit --prod
run: npm audit --omit=dev

- name: Format
run: npm run format
Expand All @@ -68,20 +54,22 @@ jobs:
run: npm run build

- name: SonarCloud Scan
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.sonar == 'true' }}
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
uses: SonarSource/sonarqube-scan-action@v6
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ env.SONAR_HOST_URL }}
Comment on lines 56 to 61
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow always runs the SonarCloud scan on PRs, but SONAR_TOKEN is taken from repo secrets. For PRs from forks, secrets are not available and the job will fail. Consider gating the Sonar steps to only run when the PR comes from the same repo (non-fork), or otherwise make the scan optional so external contributions don’t break CI.

Copilot uses AI. Check for mistakes.
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=src
-Dsonar.test.inclusions=src/**/*.test.ts,src/**/*.test.tsx,src/**/*.spec.ts,src/__tests__/**
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info

- name: SonarCloud Quality Gate
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.sonar == 'true' }}
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
uses: SonarSource/sonarqube-quality-gate-action@v1
timeout-minutes: 10
env:
Expand Down
Loading
Loading