diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..04d4193 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,51 @@ +name: Formo SDK CI Check + +on: + pull_request: + branches: + - main + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "22.14.0" + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build SDK + run: npm run build + + test: + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "22.14.0" + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run tests + run: npm test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..515215e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,190 @@ +name: Publish Package + +on: + push: + tags: + - 'v*' + +permissions: + id-token: write # Required for OIDC trusted publishing + contents: write # Required for creating GitHub releases + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for changelog generation + + - name: Verify tag is on main branch + run: | + # Check if the tag is reachable from main branch + git fetch origin main + if ! git merge-base --is-ancestor ${{ github.sha }} origin/main; then + echo "❌ Error: This tag is not on the main branch" + echo "Tags must be created on the main branch to trigger a release" + echo "Current tag: ${{ github.ref_name }}" + exit 1 + fi + echo "✅ Tag is on main branch, proceeding with release" + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "22.14.0" + cache: 'npm' + + - name: Update npm for trusted publishing + run: npm install -g npm@latest + + - name: Install dependencies + run: npm ci + + - name: Extract version from tag + id: version + run: | + VERSION=${GITHUB_REF#refs/tags/v} + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Publishing version: $VERSION" + + - name: Verify tag matches package.json version + run: | + TAG_VERSION=${{ steps.version.outputs.version }} + PKG_VERSION=$(node -p "require('./package.json').version") + + if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then + echo "❌ Error: Tag version (v$TAG_VERSION) does not match package.json version ($PKG_VERSION)" + echo "Please ensure package.json version is updated before creating the tag" + exit 1 + fi + + echo "✅ Version match confirmed: $TAG_VERSION" + + - name: Build SDK + run: npm run build + + - name: Run tests + run: npm test + + - name: Generate release notes + id: release_notes + run: | + # Get previous tag + PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "") + + # Get current date + RELEASE_DATE=$(date +%Y-%m-%d) + VERSION=${{ steps.version.outputs.version }} + + # Generate changelog with PR links + if [ -n "$PREV_TAG" ]; then + echo "Generating changelog from $PREV_TAG to $GITHUB_REF_NAME" + # Extract commits with PR numbers and format them + # Use tab as delimiter to safely handle semicolons and special characters + COMMITS=$(git log ${PREV_TAG}..HEAD --pretty=format:"%s %h" --no-merges) + else + echo "No previous tag found, using all commits" + COMMITS=$(git log --pretty=format:"%s %h" --no-merges) + fi + + # Process commits and categorize them + FEATURES="" + FIXES="" + OTHER="" + + while IFS=$'\t' read -r message hash; do + # Skip empty lines + [ -z "$message" ] && continue + + # Extract PR number if exists + if [[ $message =~ \(#([0-9]+)\) ]]; then + PR_NUM="${BASH_REMATCH[1]}" + # Remove the (#PR_NUM) from message to avoid duplication (handles with or without space) + CLEAN_MESSAGE=$(echo "$message" | sed -E 's/ ?\(#[0-9]+\)//') + PR_LINK="[#$PR_NUM](https://github.com/${{ github.repository }}/pull/$PR_NUM)" + COMMIT_LINK="[$hash](https://github.com/${{ github.repository }}/commit/$hash)" + ITEM="$CLEAN_MESSAGE ($PR_LINK) ($COMMIT_LINK)" + else + COMMIT_LINK="[$hash](https://github.com/${{ github.repository }}/commit/$hash)" + ITEM="$message ($COMMIT_LINK)" + fi + + # Categorize by prefix and strip conventional commit prefix + if [[ $message =~ ^feat(\([^\)]+\))?: ]]; then + # Strip "feat:" or "feat(scope):" from the beginning of ITEM + STRIPPED_ITEM=$(echo "$ITEM" | sed -E 's/^feat(\([^)]+\))?: //') + FEATURES="${FEATURES}- ${STRIPPED_ITEM} + " + elif [[ $message =~ ^fix(\([^\)]+\))?: ]]; then + # Strip "fix:" or "fix(scope):" from the beginning of ITEM + STRIPPED_ITEM=$(echo "$ITEM" | sed -E 's/^fix(\([^)]+\))?: //') + FIXES="${FIXES}- ${STRIPPED_ITEM} + " + else + OTHER="${OTHER}- ${ITEM} + " + fi + done <<< "$COMMITS" + + # Create release notes + cat > release_notes.md <> release_notes.md <> release_notes.md <> release_notes.md <> release_notes.md <