mirror of
https://github.com/ziex-dev/ziex.git
synced 2026-07-20 02:29:36 -06:00
ci: fix duplicate publish
This commit is contained in:
parent
e5f7397276
commit
c3e2cc127a
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@ -223,16 +223,6 @@ jobs:
|
||||
cd pkg/@ziex
|
||||
bash prepare.sh ${{ needs.resolve-version.outputs.version }}
|
||||
|
||||
- name: Publish platform packages to NPM
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ""
|
||||
run: |
|
||||
cd pkg/@ziex
|
||||
for pkg in cli-darwin-arm64 cli-darwin-x64 cli-linux-x64 cli-linux-arm64 cli-win32-x64 cli-win32-arm64; do
|
||||
echo "Publishing @ziex/$pkg..."
|
||||
npm publish --workspace "$pkg" --access public --provenance --tag ${{ needs.resolve-version.outputs.dist-tag }} || echo "Failed to publish $pkg, continuing..."
|
||||
done
|
||||
|
||||
- name: Publish @ziex/cli* to NPM
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ""
|
||||
|
||||
@ -6,7 +6,8 @@ import { downloadTemplate } from 'giget';
|
||||
import { replaceInFile } from 'replace-in-file';
|
||||
|
||||
import path from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { randomInt } from 'node:crypto';
|
||||
import { crc32 } from 'node:zlib';
|
||||
|
||||
const STATIC_TEMPLATES = [
|
||||
{ value: 'starter', label: 'Starter', hint: 'Ziex starter app' },
|
||||
@ -99,9 +100,9 @@ async function main() {
|
||||
}
|
||||
|
||||
// 3. Perform String Replacements
|
||||
const projectName = sanitizeProjectName(path.basename(targetDir));
|
||||
s.start('Customizing project files...');
|
||||
try {
|
||||
const projectName = sanitizeProjectName(path.basename(targetDir));
|
||||
await replaceInFile({
|
||||
files: `${targetDir}/**/*`,
|
||||
from: /ziex_app/g,
|
||||
@ -112,25 +113,19 @@ async function main() {
|
||||
s.stop('Replacement failed', 1);
|
||||
}
|
||||
|
||||
// 4. Fix Zig fingerprint — Zig reports the correct value when the package
|
||||
// name changes; we capture it and patch build.zig.zon automatically.
|
||||
// 4. Fix Zig fingerprint — the fingerprint is a u64 packed struct:
|
||||
// lower 32 bits = random id, upper 32 bits = CRC-32 of the package name.
|
||||
s.start('Updating package fingerprint...');
|
||||
try {
|
||||
const result = spawnSync('zig', ['build'], { cwd: targetDir, encoding: 'utf8' });
|
||||
const output = (result.stderr || '') + (result.stdout || '');
|
||||
const match = output.match(/use this value: (0x[0-9a-f]+)/);
|
||||
if (match) {
|
||||
await replaceInFile({
|
||||
files: `${targetDir}/build.zig.zon`,
|
||||
from: /\.fingerprint = 0x[0-9a-f]+/,
|
||||
to: `.fingerprint = ${match[1]}`,
|
||||
});
|
||||
s.stop('Package fingerprint updated!');
|
||||
} else {
|
||||
s.stop('Package fingerprint OK');
|
||||
}
|
||||
const fingerprint = generateZigFingerprint(projectName);
|
||||
await replaceInFile({
|
||||
files: `${targetDir}/build.zig.zon`,
|
||||
from: /\.fingerprint = 0x[0-9a-f]+/,
|
||||
to: `.fingerprint = ${fingerprint}`,
|
||||
});
|
||||
s.stop('Package fingerprint updated!');
|
||||
} catch (err) {
|
||||
s.stop('Could not update fingerprint (is zig installed?)');
|
||||
s.stop('Could not update fingerprint');
|
||||
}
|
||||
|
||||
outro(`Successfully created ${color.cyan(project)}!`);
|
||||
@ -142,4 +137,13 @@ function sanitizeProjectName(name) {
|
||||
return name.replace(/[^a-zA-Z0-9_]/g, '_');
|
||||
}
|
||||
|
||||
// Generate a Zig package fingerprint: packed u64 with
|
||||
// lower 32 bits = random id in [1, 0xFFFFFFFE], upper 32 bits = CRC-32 of name
|
||||
export function generateZigFingerprint(name) {
|
||||
const id = BigInt(randomInt(1, 0xfffffffe));
|
||||
const checksum = BigInt(crc32(Buffer.from(name)) >>> 0);
|
||||
const fingerprint = (checksum << 32n) | id;
|
||||
return '0x' + fingerprint.toString(16).padStart(16, '0');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@ -4,7 +4,7 @@
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "create-ziex",
|
||||
"dependencies": {
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "^1.1.0",
|
||||
"giget": "^3.1.2",
|
||||
"picocolors": "^1.1.1",
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
{
|
||||
"name": "create-ziex",
|
||||
"version": "0.1.0-dev.6",
|
||||
"version": "0.1.0-dev.7",
|
||||
"type": "module",
|
||||
"bin": "dist/index.js",
|
||||
"bin": {
|
||||
"create-ziex": "dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md",
|
||||
|
||||
38
pkg/create-ziex/test/fingerprint.test.ts
Normal file
38
pkg/create-ziex/test/fingerprint.test.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { describe, test, expect } from "bun:test";
|
||||
import { execSync } from "node:child_process";
|
||||
import { generateZigFingerprint } from "../bin/index.js";
|
||||
|
||||
const ZIG_RUN = "zig run test/fingerprint.zig -- ";
|
||||
const cwd = import.meta.dirname + "/..";
|
||||
|
||||
function zigGenerate(name: string): string {
|
||||
return execSync(`${ZIG_RUN} generate ${name}`, { cwd, encoding: "utf8" }).trim();
|
||||
}
|
||||
|
||||
function zigValidate(name: string, hex: string): boolean {
|
||||
return execSync(`${ZIG_RUN} validate ${name} ${hex}`, { cwd, encoding: "utf8" }).trim() === "true";
|
||||
}
|
||||
|
||||
describe("fingerprint", () => {
|
||||
const names = ["my_app", "ziex_app", "zx", "hello_world", "a"];
|
||||
|
||||
test.each(names)("node fingerprint is valid in zig for '%s'", (name) => {
|
||||
const nodeFp = generateZigFingerprint(name);
|
||||
expect(zigValidate(name, nodeFp)).toBe(true);
|
||||
});
|
||||
|
||||
test.each(names)("zig fingerprint is valid in node for '%s'", (name) => {
|
||||
const zigFp = zigGenerate(name);
|
||||
const nodeFp = generateZigFingerprint(name);
|
||||
|
||||
// Extract checksum (upper 32 bits) from both — the random id will differ
|
||||
const zigChecksum = BigInt(zigFp) >> 32n;
|
||||
const nodeChecksum = BigInt(nodeFp) >> 32n;
|
||||
expect(nodeChecksum).toBe(zigChecksum);
|
||||
});
|
||||
|
||||
test("rejects fingerprint with wrong name", () => {
|
||||
const fp = generateZigFingerprint("my_app");
|
||||
expect(zigValidate("wrong_name", fp)).toBe(false);
|
||||
});
|
||||
});
|
||||
64
pkg/create-ziex/test/fingerprint.zig
Normal file
64
pkg/create-ziex/test/fingerprint.zig
Normal file
@ -0,0 +1,64 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const Fingerprint = packed struct(u64) {
|
||||
id: u32,
|
||||
checksum: u32,
|
||||
|
||||
pub fn generate(name: []const u8) Fingerprint {
|
||||
return .{
|
||||
.id = std.crypto.random.intRangeLessThan(u32, 1, 0xffffffff),
|
||||
.checksum = std.hash.Crc32.hash(name),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn validate(n: Fingerprint, name: []const u8) bool {
|
||||
switch (n.id) {
|
||||
0x00000000, 0xffffffff => return false,
|
||||
else => return std.hash.Crc32.hash(name) == n.checksum,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn int(n: Fingerprint) u64 {
|
||||
return @bitCast(n);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
const args = try std.process.argsAlloc(std.heap.page_allocator);
|
||||
defer std.process.argsFree(std.heap.page_allocator, args);
|
||||
|
||||
const stderr = std.fs.File.stderr();
|
||||
const stdout = std.fs.File.stdout();
|
||||
|
||||
if (args.len < 3) {
|
||||
try stderr.writeAll("Usage: fingerprint <generate|validate> <name> [hex]\n");
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
const cmd = args[1];
|
||||
const name = args[2];
|
||||
|
||||
if (std.mem.eql(u8, cmd, "generate")) {
|
||||
const fp = Fingerprint.generate(name);
|
||||
var buf: [20]u8 = undefined;
|
||||
const out = std.fmt.bufPrint(&buf, "0x{x:0>16}\n", .{fp.int()}) catch unreachable;
|
||||
try stdout.writeAll(out);
|
||||
} else if (std.mem.eql(u8, cmd, "validate")) {
|
||||
if (args.len < 4) {
|
||||
try stderr.writeAll("Usage: fingerprint validate <name> <hex>\n");
|
||||
std.process.exit(1);
|
||||
}
|
||||
const hex = args[3];
|
||||
const raw = if (std.mem.startsWith(u8, hex, "0x")) hex[2..] else hex;
|
||||
const value = std.fmt.parseInt(u64, raw, 16) catch {
|
||||
try stderr.writeAll("Invalid hex value\n");
|
||||
std.process.exit(1);
|
||||
};
|
||||
const fp: Fingerprint = @bitCast(value);
|
||||
const valid = fp.validate(name);
|
||||
try stdout.writeAll(if (valid) "true\n" else "false\n");
|
||||
} else {
|
||||
try stderr.writeAll("Unknown command. Use 'generate' or 'validate'.\n");
|
||||
std.process.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user