diff --git a/.github/workflows/publish-sdk.yml b/.github/workflows/publish-sdk.yml new file mode 100644 index 0000000..fafeca3 --- /dev/null +++ b/.github/workflows/publish-sdk.yml @@ -0,0 +1,124 @@ +name: Publish SDK + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v1 + with: + bun-version: "1.3.2" + + - name: Install SDK dependencies + working-directory: packages/scrawn + run: bun install + + - name: Resolve and validate release version + working-directory: packages/scrawn + run: | + TAG="${GITHUB_REF_NAME}" + if [[ "${TAG}" == v* ]]; then + VERSION="${TAG#v}" + else + VERSION="${TAG}" + fi + + CURRENT_VERSION=$(node -p "require('./package.json').version") + CURRENT_VERSION="${CURRENT_VERSION}" TARGET_VERSION="${VERSION}" node - <<'NODE' + const current = process.env.CURRENT_VERSION; + const target = process.env.TARGET_VERSION; + const semverPattern = /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/; + + if (!semverPattern.test(current) || !semverPattern.test(target)) { + console.error(`Invalid version format. Current: ${current}, Target: ${target}`); + process.exit(1); + } + + const parse = (version) => { + const [core, prerelease] = version.split('-', 2); + const parts = core.split('.').map((part) => Number(part)); + return { parts, prerelease }; + }; + + const compareIdentifiers = (a, b) => { + const aNum = Number(a); + const bNum = Number(b); + const aIsNum = !Number.isNaN(aNum) && String(aNum) === a; + const bIsNum = !Number.isNaN(bNum) && String(bNum) === b; + if (aIsNum && bIsNum) return aNum - bNum; + if (aIsNum) return -1; + if (bIsNum) return 1; + return a.localeCompare(b); + }; + + const comparePrerelease = (a, b) => { + if (!a && !b) return 0; + if (!a && b) return 1; + if (a && !b) return -1; + const aParts = a.split('.'); + const bParts = b.split('.'); + const len = Math.max(aParts.length, bParts.length); + for (let i = 0; i < len; i += 1) { + const aPart = aParts[i]; + const bPart = bParts[i]; + if (aPart === undefined) return -1; + if (bPart === undefined) return 1; + const diff = compareIdentifiers(aPart, bPart); + if (diff !== 0) return diff; + } + return 0; + }; + + const compareVersions = (a, b) => { + const aParsed = parse(a); + const bParsed = parse(b); + for (let i = 0; i < 3; i += 1) { + const diff = (aParsed.parts[i] || 0) - (bParsed.parts[i] || 0); + if (diff !== 0) return diff; + } + return comparePrerelease(aParsed.prerelease, bParsed.prerelease); + }; + + const diff = compareVersions(target, current); + if (diff <= 0) { + console.error(`Release version ${target} must be higher than package.json version ${current}.`); + process.exit(1); + } + NODE + + echo "VERSION=${VERSION}" >> "$GITHUB_ENV" + + - name: Update package.json version + working-directory: packages/scrawn + run: npm version "${VERSION}" --no-git-tag-version + env: + VERSION: ${{ env.VERSION }} + + - name: Run SDK tests + working-directory: packages/scrawn + run: bun run test + + - name: Clean and build SDK + run: bash ./clean_build.sh + + - name: Publish to npm + working-directory: packages/scrawn + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + VERSION: ${{ env.VERSION }} + run: | + if [[ "${VERSION}" == *"-"* ]]; then + PRERELEASE="${VERSION#*-}" + PUBLISH_TAG="${PRERELEASE%%.*}" + else + PUBLISH_TAG="latest" + fi + echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc + bun publish --tag "${PUBLISH_TAG}" --access public --no-git-checks diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3a23b1b..aa03adb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,9 +2,6 @@ name: SDK Tests on: pull_request: - paths: - - "packages/scrawn/**" - - ".github/workflows/tests.yml" jobs: sdk-tests: