@techninja/clearstack 0.3.19 → 0.3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,6 +22,7 @@ export async function writePackageJson(dest, vars, existing) {
22
22
  postinstall: 'node scripts/setup.js',
23
23
  test: 'node scripts/test.js',
24
24
  spec: 'node scripts/spec.js',
25
+ release: 'node scripts/release.js',
25
26
  };
26
27
 
27
28
  const specDeps = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techninja/clearstack",
3
- "version": "0.3.19",
3
+ "version": "0.3.21",
4
4
  "type": "module",
5
5
  "description": "A no-build web component framework specification — scaffold, validate, and evolve spec-compliant projects",
6
6
  "bin": {
@@ -0,0 +1,53 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write
11
+
12
+ jobs:
13
+ release:
14
+ name: Publish to npm + GitHub Release
15
+ runs-on: ubuntu-latest
16
+
17
+ steps:
18
+ - uses: actions/checkout@v6
19
+ with:
20
+ fetch-depth: 0
21
+
22
+ - uses: actions/setup-node@v6
23
+ with:
24
+ node-version: 24
25
+ registry-url: https://registry.npmjs.org
26
+
27
+ - run: npm ci
28
+
29
+ - name: Publish to npm
30
+ run: npm publish --provenance --access public
31
+ env:
32
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
33
+
34
+ - name: Generate changelog from commits
35
+ id: changelog
36
+ run: |
37
+ PREV_TAG=$(git tag --sort=-v:refname | sed -n '2p')
38
+ if [ -z "$PREV_TAG" ]; then
39
+ LOG=$(git log --pretty=format:"- %s (%h)" HEAD)
40
+ else
41
+ LOG=$(git log --pretty=format:"- %s (%h)" "$PREV_TAG"..HEAD)
42
+ fi
43
+ echo "log<<EOF" >> "$GITHUB_OUTPUT"
44
+ echo "$LOG" >> "$GITHUB_OUTPUT"
45
+ echo "EOF" >> "$GITHUB_OUTPUT"
46
+
47
+ - name: Create GitHub Release
48
+ uses: softprops/action-gh-release@v2
49
+ with:
50
+ body: |
51
+ ## Changes
52
+ ${{ steps.changelog.outputs.log }}
53
+ generate_release_notes: true
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Release helper — bumps version, updates changelog, commits, and tags.
5
+ * Platform-aware: runs sync-vendor.js if it exists.
6
+ * Usage: node scripts/release.js [patch|minor|major]
7
+ * @module scripts/release
8
+ */
9
+
10
+ import { execSync } from 'node:child_process';
11
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs';
12
+ import { resolve, dirname } from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+
15
+ const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
16
+ const bump = process.argv[2] || 'patch';
17
+
18
+ if (!['patch', 'minor', 'major'].includes(bump)) {
19
+ console.error('Usage: node scripts/release.js [patch|minor|major]');
20
+ process.exit(1);
21
+ }
22
+
23
+ const run = (cmd) => execSync(cmd, { cwd: ROOT, stdio: 'inherit' });
24
+ const out = (cmd) => execSync(cmd, { cwd: ROOT, encoding: 'utf-8' }).trim();
25
+
26
+ // Gate: clean working tree (allow staged changes)
27
+ const dirty = out('git diff --name-only HEAD').split('\n').filter(Boolean);
28
+ if (dirty.length > 0) {
29
+ console.error('\n❌ Uncommitted changes — commit or stash first:\n');
30
+ dirty.forEach((f) => console.error(` ${f}`));
31
+ process.exit(1);
32
+ }
33
+
34
+ // Bump version
35
+ const pkgPath = resolve(ROOT, 'package.json');
36
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
37
+ const [ma, mi, pa] = pkg.version.split('.').map(Number);
38
+ const next =
39
+ bump === 'major' ? `${ma + 1}.0.0` : bump === 'minor' ? `${ma}.${mi + 1}.0` : `${ma}.${mi}.${pa + 1}`;
40
+ pkg.version = next;
41
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
42
+ console.log(`\n📦 ${pkg.name} → v${next}\n`);
43
+
44
+ // Platform: sync vendor if applicable
45
+ const syncScript = resolve(ROOT, 'scripts/sync-vendor.js');
46
+ if (existsSync(syncScript)) {
47
+ console.log('🔄 Syncing vendor...');
48
+ run('node scripts/sync-vendor.js');
49
+ }
50
+
51
+ // Spec check
52
+ console.log('\n🔍 Running spec checks...\n');
53
+ run('npm run spec -- check all');
54
+
55
+ // Changelog
56
+ const changelogPath = resolve(ROOT, 'CHANGELOG.md');
57
+ const lastTag = out('git tag --sort=-v:refname').split('\n')[0] || '';
58
+ const range = lastTag ? `${lastTag}..HEAD` : 'HEAD';
59
+ const log = out(`git log ${range} --pretty=format:"- %s"`);
60
+ const date = new Date().toISOString().split('T')[0];
61
+ const entry = `## [${next}] - ${date}\n\n${log || '- Initial release'}\n`;
62
+
63
+ if (existsSync(changelogPath)) {
64
+ const cl = readFileSync(changelogPath, 'utf-8');
65
+ const marker = '## [Unreleased]';
66
+ const updated = cl.includes(marker)
67
+ ? cl.replace(marker, `${marker}\n\n${entry}`)
68
+ : `${entry}\n\n${cl}`;
69
+ writeFileSync(changelogPath, updated);
70
+ } else {
71
+ const header = '# Changelog\n\n## [Unreleased]\n\n';
72
+ writeFileSync(changelogPath, header + entry);
73
+ }
74
+ console.log('📝 Updated CHANGELOG.md');
75
+
76
+ // Commit + tag
77
+ run('git add -A');
78
+ run(`git commit -m "release: v${next}"`);
79
+ run(`git tag v${next}`);
80
+ console.log(`\n🏷️ Tagged v${next}`);
81
+ console.log(`\n git push && git push --tags\n`);