@tinyrack/devsync 1.0.0 → 1.0.3

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.
package/README.md CHANGED
@@ -53,6 +53,20 @@ If you want the `devsync` command available from this checkout during developmen
53
53
  npm link
54
54
  ```
55
55
 
56
+ ## Release
57
+
58
+ - CI runs on every push and pull request with `npm run check` on Node.js 24.
59
+ - npm publishing runs automatically when a Git tag matching `v*.*.*` is pushed.
60
+ - The release workflow uses npm Trusted Publishing, so npm access is granted through GitHub Actions OIDC instead of an `NPM_TOKEN` secret.
61
+ - The release workflow fails if the pushed tag does not match `package.json` `version`.
62
+
63
+ Typical release flow:
64
+
65
+ ```bash
66
+ npm version patch
67
+ git push --follow-tags
68
+ ```
69
+
56
70
  ## Storage Layout
57
71
 
58
72
  - Sync repo: `~/.config/devsync/sync`
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@tinyrack/devsync",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "A personal CLI tool for git-backed configuration sync.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "winetree94",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://git.winetree94.com/winetree94/devsync.git"
10
+ "url": "git+https://github.com/tinyrack-net/devsync.git"
11
11
  },
12
- "homepage": "https://git.winetree94.com/winetree94/devsync",
12
+ "homepage": "https://github.com/tinyrack-net/devsync#readme",
13
13
  "bugs": {
14
- "url": "https://git.winetree94.com/winetree94/devsync/issues"
14
+ "url": "https://github.com/tinyrack-net/devsync/issues"
15
15
  },
16
16
  "publishConfig": {
17
17
  "access": "public"
@@ -62,7 +62,10 @@
62
62
  "coverage": "vitest run --coverage",
63
63
  "check": "npm run typecheck && biome check . && npm run test",
64
64
  "check:fix": "biome check --write .",
65
- "format": "biome format --write ."
65
+ "format": "biome format --write .",
66
+ "release:patch": "npm version patch -m \"chore(release): %s\"",
67
+ "release:minor": "npm version minor -m \"chore(release): %s\"",
68
+ "release:major": "npm version major -m \"chore(release): %s\""
66
69
  },
67
70
  "dependencies": {
68
71
  "@oclif/core": "^4.9.0",
@@ -0,0 +1,105 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import {
4
+ formatSyncAddResult,
5
+ formatSyncForgetResult,
6
+ formatSyncInitResult,
7
+ formatSyncPullResult,
8
+ formatSyncPushResult,
9
+ formatSyncSetResult,
10
+ } from "#app/cli/sync-output.ts";
11
+
12
+ describe("sync output formatting", () => {
13
+ it("formats init results for cloned repositories", () => {
14
+ expect(
15
+ formatSyncInitResult({
16
+ alreadyInitialized: false,
17
+ configPath: "/tmp/sync/config.json",
18
+ entryCount: 2,
19
+ generatedIdentity: true,
20
+ gitAction: "cloned",
21
+ gitSource: "/tmp/remote",
22
+ identityFile: "/tmp/xdg/devsync/age/keys.txt",
23
+ recipientCount: 3,
24
+ ruleCount: 4,
25
+ syncDirectory: "/tmp/sync",
26
+ }),
27
+ ).toBe(
28
+ [
29
+ "Initialized sync directory.",
30
+ "Sync directory: /tmp/sync",
31
+ "Config file: /tmp/sync/config.json",
32
+ "Age identity file: /tmp/xdg/devsync/age/keys.txt",
33
+ "Git repository: cloned from /tmp/remote",
34
+ "Age bootstrap: generated a new local identity.",
35
+ "Summary: 3 recipients, 2 entries, 4 rules.",
36
+ "",
37
+ ].join("\n"),
38
+ );
39
+ });
40
+
41
+ it("formats add, forget, and set results", () => {
42
+ expect(
43
+ formatSyncAddResult({
44
+ alreadyTracked: false,
45
+ configPath: "/tmp/sync/config.json",
46
+ kind: "file",
47
+ localPath: "/tmp/home/.zshrc",
48
+ mode: "secret",
49
+ repoPath: ".zshrc",
50
+ syncDirectory: "/tmp/sync",
51
+ }),
52
+ ).toContain("Added sync target.\n");
53
+ expect(
54
+ formatSyncForgetResult({
55
+ configPath: "/tmp/sync/config.json",
56
+ localPath: "/tmp/home/.zshrc",
57
+ plainArtifactCount: 1,
58
+ repoPath: ".zshrc",
59
+ secretArtifactCount: 2,
60
+ syncDirectory: "/tmp/sync",
61
+ }),
62
+ ).toContain("Removed repo artifacts: 1 plain, 2 secret.\n");
63
+ expect(
64
+ formatSyncSetResult({
65
+ action: "updated",
66
+ configPath: "/tmp/sync/config.json",
67
+ entryRepoPath: "bundle",
68
+ localPath: "/tmp/home/bundle/private.json",
69
+ mode: "ignore",
70
+ repoPath: "bundle/private.json",
71
+ scope: "exact",
72
+ syncDirectory: "/tmp/sync",
73
+ }),
74
+ ).toContain("Scope: exact rule\nAction: updated\n");
75
+ });
76
+
77
+ it("formats push and pull dry-run summaries", () => {
78
+ expect(
79
+ formatSyncPushResult({
80
+ configPath: "/tmp/sync/config.json",
81
+ deletedArtifactCount: 4,
82
+ directoryCount: 1,
83
+ dryRun: true,
84
+ encryptedFileCount: 2,
85
+ plainFileCount: 3,
86
+ symlinkCount: 1,
87
+ syncDirectory: "/tmp/sync",
88
+ }),
89
+ ).toContain("No filesystem changes were made.\n");
90
+ expect(
91
+ formatSyncPullResult({
92
+ configPath: "/tmp/sync/config.json",
93
+ decryptedFileCount: 2,
94
+ deletedLocalCount: 5,
95
+ directoryCount: 1,
96
+ dryRun: true,
97
+ plainFileCount: 3,
98
+ symlinkCount: 1,
99
+ syncDirectory: "/tmp/sync",
100
+ }),
101
+ ).toContain(
102
+ "local paths would be removed.\nNo filesystem changes were made.\n",
103
+ );
104
+ });
105
+ });