rampway 0.2.1

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.
Files changed (143) hide show
  1. package/README.md +183 -0
  2. package/build/src/cli.d.ts +3 -0
  3. package/build/src/cli.d.ts.map +1 -0
  4. package/build/src/cli.js +104 -0
  5. package/build/src/cli.js.map +1 -0
  6. package/build/src/commands/context.d.ts +12 -0
  7. package/build/src/commands/context.d.ts.map +1 -0
  8. package/build/src/commands/context.js +16 -0
  9. package/build/src/commands/context.js.map +1 -0
  10. package/build/src/commands/deploy.d.ts +6 -0
  11. package/build/src/commands/deploy.d.ts.map +1 -0
  12. package/build/src/commands/deploy.js +14 -0
  13. package/build/src/commands/deploy.js.map +1 -0
  14. package/build/src/commands/doctor.d.ts +14 -0
  15. package/build/src/commands/doctor.d.ts.map +1 -0
  16. package/build/src/commands/doctor.js +54 -0
  17. package/build/src/commands/doctor.js.map +1 -0
  18. package/build/src/commands/init.d.ts +8 -0
  19. package/build/src/commands/init.d.ts.map +1 -0
  20. package/build/src/commands/init.js +42 -0
  21. package/build/src/commands/init.js.map +1 -0
  22. package/build/src/commands/plan.d.ts +6 -0
  23. package/build/src/commands/plan.d.ts.map +1 -0
  24. package/build/src/commands/plan.js +24 -0
  25. package/build/src/commands/plan.js.map +1 -0
  26. package/build/src/commands/releases.d.ts +27 -0
  27. package/build/src/commands/releases.d.ts.map +1 -0
  28. package/build/src/commands/releases.js +91 -0
  29. package/build/src/commands/releases.js.map +1 -0
  30. package/build/src/commands/rollback.d.ts +6 -0
  31. package/build/src/commands/rollback.d.ts.map +1 -0
  32. package/build/src/commands/rollback.js +12 -0
  33. package/build/src/commands/rollback.js.map +1 -0
  34. package/build/src/commands/rollbridge.d.ts +21 -0
  35. package/build/src/commands/rollbridge.d.ts.map +1 -0
  36. package/build/src/commands/rollbridge.js +69 -0
  37. package/build/src/commands/rollbridge.js.map +1 -0
  38. package/build/src/commands/validate.d.ts +6 -0
  39. package/build/src/commands/validate.d.ts.map +1 -0
  40. package/build/src/commands/validate.js +12 -0
  41. package/build/src/commands/validate.js.map +1 -0
  42. package/build/src/config/load-config.d.ts +10 -0
  43. package/build/src/config/load-config.d.ts.map +1 -0
  44. package/build/src/config/load-config.js +71 -0
  45. package/build/src/config/load-config.js.map +1 -0
  46. package/build/src/config/validate-config.d.ts +7 -0
  47. package/build/src/config/validate-config.d.ts.map +1 -0
  48. package/build/src/config/validate-config.js +117 -0
  49. package/build/src/config/validate-config.js.map +1 -0
  50. package/build/src/core/deploy-runner.d.ts +46 -0
  51. package/build/src/core/deploy-runner.d.ts.map +1 -0
  52. package/build/src/core/deploy-runner.js +221 -0
  53. package/build/src/core/deploy-runner.js.map +1 -0
  54. package/build/src/core/expo-web-artifacts.d.ts +10 -0
  55. package/build/src/core/expo-web-artifacts.d.ts.map +1 -0
  56. package/build/src/core/expo-web-artifacts.js +16 -0
  57. package/build/src/core/expo-web-artifacts.js.map +1 -0
  58. package/build/src/core/git-source.d.ts +22 -0
  59. package/build/src/core/git-source.d.ts.map +1 -0
  60. package/build/src/core/git-source.js +63 -0
  61. package/build/src/core/git-source.js.map +1 -0
  62. package/build/src/core/health-checks.d.ts +8 -0
  63. package/build/src/core/health-checks.d.ts.map +1 -0
  64. package/build/src/core/health-checks.js +19 -0
  65. package/build/src/core/health-checks.js.map +1 -0
  66. package/build/src/core/hooks.d.ts +12 -0
  67. package/build/src/core/hooks.d.ts.map +1 -0
  68. package/build/src/core/hooks.js +26 -0
  69. package/build/src/core/hooks.js.map +1 -0
  70. package/build/src/core/locks.d.ts +16 -0
  71. package/build/src/core/locks.d.ts.map +1 -0
  72. package/build/src/core/locks.js +32 -0
  73. package/build/src/core/locks.js.map +1 -0
  74. package/build/src/core/node-package-tasks.d.ts +26 -0
  75. package/build/src/core/node-package-tasks.d.ts.map +1 -0
  76. package/build/src/core/node-package-tasks.js +143 -0
  77. package/build/src/core/node-package-tasks.js.map +1 -0
  78. package/build/src/core/path-change-gate.d.ts +15 -0
  79. package/build/src/core/path-change-gate.d.ts.map +1 -0
  80. package/build/src/core/path-change-gate.js +95 -0
  81. package/build/src/core/path-change-gate.js.map +1 -0
  82. package/build/src/core/paths.d.ts +7 -0
  83. package/build/src/core/paths.d.ts.map +1 -0
  84. package/build/src/core/paths.js +20 -0
  85. package/build/src/core/paths.js.map +1 -0
  86. package/build/src/core/redaction.d.ts +22 -0
  87. package/build/src/core/redaction.d.ts.map +1 -0
  88. package/build/src/core/redaction.js +39 -0
  89. package/build/src/core/redaction.js.map +1 -0
  90. package/build/src/core/release-id.d.ts +6 -0
  91. package/build/src/core/release-id.d.ts.map +1 -0
  92. package/build/src/core/release-id.js +20 -0
  93. package/build/src/core/release-id.js.map +1 -0
  94. package/build/src/core/release-manager.d.ts +49 -0
  95. package/build/src/core/release-manager.d.ts.map +1 -0
  96. package/build/src/core/release-manager.js +115 -0
  97. package/build/src/core/release-manager.js.map +1 -0
  98. package/build/src/core/task-runner.d.ts +38 -0
  99. package/build/src/core/task-runner.d.ts.map +1 -0
  100. package/build/src/core/task-runner.js +102 -0
  101. package/build/src/core/task-runner.js.map +1 -0
  102. package/build/src/core/velocious-migrate.d.ts +11 -0
  103. package/build/src/core/velocious-migrate.d.ts.map +1 -0
  104. package/build/src/core/velocious-migrate.js +20 -0
  105. package/build/src/core/velocious-migrate.js.map +1 -0
  106. package/build/src/runtimes/index.d.ts +56 -0
  107. package/build/src/runtimes/index.d.ts.map +1 -0
  108. package/build/src/runtimes/index.js +132 -0
  109. package/build/src/runtimes/index.js.map +1 -0
  110. package/build/src/runtimes/none-runtime.d.ts +22 -0
  111. package/build/src/runtimes/none-runtime.d.ts.map +1 -0
  112. package/build/src/runtimes/none-runtime.js +23 -0
  113. package/build/src/runtimes/none-runtime.js.map +1 -0
  114. package/build/src/runtimes/rollbridge-runtime.d.ts +137 -0
  115. package/build/src/runtimes/rollbridge-runtime.d.ts.map +1 -0
  116. package/build/src/runtimes/rollbridge-runtime.js +224 -0
  117. package/build/src/runtimes/rollbridge-runtime.js.map +1 -0
  118. package/build/src/tasks.d.ts +5 -0
  119. package/build/src/tasks.d.ts.map +1 -0
  120. package/build/src/tasks.js +5 -0
  121. package/build/src/tasks.js.map +1 -0
  122. package/build/src/test-helpers.d.ts +25 -0
  123. package/build/src/test-helpers.d.ts.map +1 -0
  124. package/build/src/test-helpers.js +40 -0
  125. package/build/src/test-helpers.js.map +1 -0
  126. package/build/src/transports/local-transport.d.ts +67 -0
  127. package/build/src/transports/local-transport.d.ts.map +1 -0
  128. package/build/src/transports/local-transport.js +121 -0
  129. package/build/src/transports/local-transport.js.map +1 -0
  130. package/build/src/transports/ssh-transport.d.ts +189 -0
  131. package/build/src/transports/ssh-transport.d.ts.map +1 -0
  132. package/build/src/transports/ssh-transport.js +369 -0
  133. package/build/src/transports/ssh-transport.js.map +1 -0
  134. package/build/src/types.d.ts +290 -0
  135. package/build/src/types.d.ts.map +1 -0
  136. package/build/src/types.js +8 -0
  137. package/build/src/types.js.map +1 -0
  138. package/docs/config-reference.md +264 -0
  139. package/docs/migration-from-capistrano.md +167 -0
  140. package/docs/roadmap.md +27 -0
  141. package/examples/local/rampway.config.mjs +20 -0
  142. package/examples/monorepo/rampway.config.mjs +73 -0
  143. package/package.json +92 -0
@@ -0,0 +1,167 @@
1
+ # Migrating from Capistrano to Rampway
2
+
3
+ Rampway is a JS-native alternative to Capistrano for Node projects. This guide maps Capistrano concepts to their Rampway equivalents and walks through a migration.
4
+
5
+ ## Quick reference
6
+
7
+ | Capistrano | Rampway |
8
+ |------------|---------|
9
+ | `config/deploy.rb` | `rampway.config.mjs` |
10
+ | `config/deploy/production.rb` | stage config in `stages.production` |
11
+ | `set :application, "myapp"` | `application: "myapp"` |
12
+ | `set :deploy_to, "/path"` | `deployTo: "/path"` |
13
+ | `set :keep_releases, 5` | `keepReleases: 5` |
14
+ | `set :linked_files, [...]` | `linkedFiles: [...]` |
15
+ | `set :linked_dirs, [...]` | `linkedDirs: [...]` |
16
+ | `server "host", user: "...", roles: [...]` | `hosts: [{host, user, roles}]` |
17
+ | `SSHKit` | `transport: {type: "ssh"}` |
18
+ | `after/before` hooks | `tasks` run in config order, or use lifecycle `hooks` for phase-specific callbacks |
19
+ | `deploy:starting` … `deploy:finished` | task groups + runtime deploy |
20
+ | `cap production deploy` | `rampway deploy production` |
21
+ | `cap production deploy:rollback` | `rampway rollback production` |
22
+ | `current` symlink | same |
23
+ | `releases/` directory | same |
24
+ | `shared/` directory | same |
25
+ | `REVISION` file | `REVISION` + `TRESTLE_RELEASE.json` |
26
+
27
+ ## Step-by-step migration
28
+
29
+ ### 1. Install Rampway
30
+
31
+ Rampway is a dev dependency in your project:
32
+
33
+ ```bash
34
+ npm install --save-dev rampway
35
+ ```
36
+
37
+ Or run `rampway init` to scaffold a new config.
38
+
39
+ ### 2. Create the config
40
+
41
+ Run `rampway init` or create `rampway.config.mjs` manually:
42
+
43
+ ```js
44
+ export default {
45
+ application: "myapp",
46
+ stages: {
47
+ production: {
48
+ deployTo: "/home/dev/myapp",
49
+ strategy: "local-copy",
50
+ transport: {type: "ssh"},
51
+ hosts: [{host: "server.example", user: "dev", roles: ["app", "web"]}],
52
+ keepReleases: 5,
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ ### 3. Convert linked files and dirs
59
+
60
+ Capistrano:
61
+
62
+ ```ruby
63
+ set :linked_files, %w[.env backend/src/config/secrets.js]
64
+ set :linked_dirs, %w[log tmp/pids tmp/cache storage]
65
+ ```
66
+
67
+ Rampway:
68
+
69
+ ```js
70
+ linkedFiles: [
71
+ {path: ".env", required: true},
72
+ {path: "backend/src/config/secrets.js"}
73
+ ],
74
+ linkedDirs: ["log", "tmp/pids", "tmp/cache", "storage"],
75
+ ```
76
+
77
+ Rampway linked files can be `required` (fail deploy if missing) or optional (silently skipped).
78
+
79
+ ### 4. Convert hooks to task groups
80
+
81
+ Capistrano hooks run at specific points in the deploy lifecycle:
82
+
83
+ ```ruby
84
+ after "deploy:published", "restart"
85
+ ```
86
+
87
+ In Rampway, task groups run in config order within the deploy pipeline. No explicit before/after hooks — just order your task groups:
88
+
89
+ ```js
90
+ tasks: {
91
+ install: [...],
92
+ migrate: [...],
93
+ build: [...]
94
+ }
95
+ ```
96
+
97
+ Task groups run after shared links are created, before the runtime handoff and publish. Use task helpers for common Node workflows:
98
+
99
+ ```js
100
+ import {npmInstall, velociousMigrate, onlyIfChanged} from "rampway/tasks"
101
+
102
+ tasks: {
103
+ install: [npmInstall({cwd: "backend", production: true})],
104
+ migrate: [velociousMigrate({cwd: "backend", env: {NODE_ENV: "production"}})]
105
+ }
106
+ ```
107
+
108
+ ### 5. Convert process management
109
+
110
+ Capistrano relies on SSH-based process management (puma, sidekiq, etc.) or custom tasks:
111
+
112
+ ```ruby
113
+ namespace :deploy do
114
+ task :restart do
115
+ on roles(:app) do
116
+ execute :sudo, :systemctl, :restart, "myapp"
117
+ end
118
+ end
119
+ end
120
+ ```
121
+
122
+ In Rampway, process management is delegated to a runtime adapter. For Node projects, use Rollbridge:
123
+
124
+ ```js
125
+ runtime: {
126
+ type: "rollbridge",
127
+ packageDir: "backend",
128
+ healthPath: "/health",
129
+ daemonLogPath: "/home/dev/myapp/shared/log/rollbridge.log",
130
+ daemonPidPath: "/home/dev/myapp/shared/tmp/pids/rollbridge.pid"
131
+ }
132
+ ```
133
+
134
+ Rollbridge handles zero-downtime restarts, health checks, and log access. Rampway orchestrates the release lifecycle; Rollbridge owns the process.
135
+
136
+ For simple setups without a process manager, use `runtime: {type: "none"}` and handle process restarts yourself via task commands.
137
+
138
+ ### 6. Run the first deploy
139
+
140
+ ```bash
141
+ # Validate
142
+ rampway validate production
143
+
144
+ # Plan (dry run)
145
+ rampway plan production
146
+
147
+ # Deploy
148
+ rampway deploy production --yes
149
+ ```
150
+
151
+ ### 7. Verify and cleanup
152
+
153
+ ```bash
154
+ rampway status production
155
+ rampway releases production
156
+ ```
157
+
158
+ After verifying the first deploy works, remove your old Capistrano config files.
159
+
160
+ ## Key differences
161
+
162
+ - **No Ruby dependency.** Rampway runs on Node.js, matching your JS/TS stack.
163
+ - **Task groups replace hooks.** Order task groups instead of registering `after`/`before` callbacks. For Capistrano-style lifecycle callbacks, use `hooks` with named phases like `before_publish` and `after_cleanup`.
164
+ - **Runtime adapters replace process management tasks.** Rollbridge or a custom adapter handles zero-downtime handoff.
165
+ - **ESM config.** `rampway.config.mjs` uses ES module syntax, not Ruby DSL.
166
+ - **Health checks are built in.** Add `healthChecks` to verify deploy readiness before publishing.
167
+ - **Path-change gating.** Use `onlyIfChanged()` to skip task groups when nothing changed in their paths.
@@ -0,0 +1,27 @@
1
+ # Roadmap
2
+
3
+ ## Epic 1 — Project foundation
4
+
5
+ - [x] Create GitHub repo and package scaffold
6
+ - [x] Add CLI skeleton and command router
7
+ - [x] Add config loader and validator
8
+ - [x] Add test/lint setup
9
+ - [x] Add README with product goals and MVP scope
10
+ - [ ] Add TensorBuzz project/checks
11
+
12
+ ## Epic 2 — Release lifecycle
13
+
14
+ - [x] Implement release directory model
15
+ - [x] Implement deploy lock
16
+ - [x] Implement linked files/dirs
17
+ - [x] Implement release metadata
18
+ - [x] Implement current symlink publish
19
+ - [x] Implement cleanup old releases
20
+ - [x] Implement rollback
21
+
22
+ ## Next
23
+
24
+ 1. Add SSH transport with OpenSSH command construction tests.
25
+ 2. Expand Rollbridge runtime execution/status/log wrappers.
26
+ 3. Add doctor/status diagnostics.
27
+ 4. Dogfood with Routergeist staging/local deploy target.
@@ -0,0 +1,20 @@
1
+ import path from "node:path"
2
+
3
+ const deployTo = process.env.RAMPWAY_LOCAL_DEPLOY_TO ?? path.join(process.cwd(), ".rampway-local-target")
4
+
5
+ export default {
6
+ application: "rampway-example",
7
+ stages: {
8
+ local: {
9
+ deployTo,
10
+ strategy: "local-copy",
11
+ transport: {type: "local"},
12
+ keepReleases: 2,
13
+ linkedFiles: [],
14
+ linkedDirs: ["log", "tmp/pids"],
15
+ tasks: {},
16
+ runtime: {type: "none"},
17
+ healthChecks: [{name: "package", path: "package.json"}]
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,73 @@
1
+ import path from "node:path"
2
+ import {npmInstall, velociousMigrate, checkExpoWebArtifacts, onlyIfChanged} from "../../src/tasks.js"
3
+
4
+ const deployRoot = process.env.RAMPWAY_MONOREPO_DEPLOY_TO ?? path.join(process.cwd(), ".rampway-monorepo-target")
5
+
6
+ export default {
7
+ application: "rampway-monorepo-example",
8
+ stages: {
9
+ local: {
10
+ deployTo: deployRoot,
11
+ strategy: "local-copy",
12
+ transport: {type: "local"},
13
+ keepReleases: 2,
14
+ linkedFiles: [],
15
+ linkedDirs: ["log", "tmp/pids"],
16
+ tasks: {
17
+ install: [
18
+ onlyIfChanged(["backend"], npmInstall({cwd: "backend", production: true})),
19
+ onlyIfChanged(["app"], npmInstall({cwd: "app"}))
20
+ ],
21
+ migrate: [
22
+ onlyIfChanged(["backend"], velociousMigrate({cwd: "backend", env: {NODE_ENV: "production"}}))
23
+ ],
24
+ build: [
25
+ "cd app && npm run web:export",
26
+ checkExpoWebArtifacts({dir: "app/dist"})
27
+ ]
28
+ },
29
+ runtime: {type: "none"},
30
+ healthChecks: [{name: "backend-package", path: "backend/package.json"}]
31
+ },
32
+ production: {
33
+ deployTo: "/home/dev/myapp",
34
+ strategy: "local-copy",
35
+ transport: {type: "ssh"},
36
+ hosts: [{host: "server.example", user: "dev", roles: ["app", "web"]}],
37
+ keepReleases: 5,
38
+ linkedFiles: [
39
+ {path: "backend/src/config/secrets.js", required: true},
40
+ {path: ".env", required: true}
41
+ ],
42
+ linkedDirs: ["log", "tmp/pids", "tmp/cache", "storage"],
43
+ tasks: {
44
+ install: [
45
+ onlyIfChanged(["backend"], npmInstall({cwd: "backend", production: true})),
46
+ onlyIfChanged(["app"], npmInstall({cwd: "app", production: true}))
47
+ ],
48
+ migrate: [
49
+ onlyIfChanged(["backend"], velociousMigrate({cwd: "backend", env: {NODE_ENV: "production"}}))
50
+ ],
51
+ build: [
52
+ "cd app && npm run web:export",
53
+ checkExpoWebArtifacts({dir: "app/dist"})
54
+ ]
55
+ },
56
+ runtime: {
57
+ type: "rollbridge",
58
+ command: "npx rollbridge",
59
+ packageDir: "backend",
60
+ config: "backend/config/rollbridge.production.mjs",
61
+ healthPath: "/health",
62
+ daemonLogPath: "/home/dev/myapp/shared/log/rollbridge.log",
63
+ daemonPidPath: "/home/dev/myapp/shared/tmp/pids/rollbridge.pid",
64
+ socketPath: "/tmp/rollbridge-myapp.sock",
65
+ versionPath: "/home/dev/myapp/shared/tmp/rollbridge-version"
66
+ },
67
+ healthChecks: [
68
+ {name: "backend-package", path: "backend/package.json"},
69
+ {name: "app-package", path: "app/package.json"}
70
+ ]
71
+ }
72
+ }
73
+ }
package/package.json ADDED
@@ -0,0 +1,92 @@
1
+ {
2
+ "name": "rampway",
3
+ "version": "0.2.1",
4
+ "description": "JS-native Capistrano-style release-directory deployments with Rollbridge integration.",
5
+ "type": "module",
6
+ "private": false,
7
+ "license": "UNLICENSED",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/kaspernj/rampway.git"
11
+ },
12
+ "homepage": "https://github.com/kaspernj/rampway#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/kaspernj/rampway/issues"
15
+ },
16
+ "author": "Kasper Johansen",
17
+ "keywords": [
18
+ "deploy",
19
+ "deployment",
20
+ "capistrano",
21
+ "release",
22
+ "release-directory",
23
+ "rollback",
24
+ "monorepo",
25
+ "node",
26
+ "expo",
27
+ "velocious",
28
+ "rollbridge",
29
+ "zero-downtime"
30
+ ],
31
+ "bin": {
32
+ "rampway": "build/src/cli.js"
33
+ },
34
+ "main": "build/src/tasks.js",
35
+ "types": "build/src/tasks.d.ts",
36
+ "exports": {
37
+ ".": {
38
+ "types": "./build/src/tasks.d.ts",
39
+ "default": "./build/src/tasks.js"
40
+ },
41
+ "./tasks": {
42
+ "types": "./build/src/tasks.d.ts",
43
+ "default": "./build/src/tasks.js"
44
+ },
45
+ "./tasks.js": {
46
+ "types": "./build/src/tasks.d.ts",
47
+ "default": "./build/src/tasks.js"
48
+ },
49
+ "./test-helpers": {
50
+ "types": "./build/src/test-helpers.d.ts",
51
+ "default": "./build/src/test-helpers.js"
52
+ },
53
+ "./test-helpers.js": {
54
+ "types": "./build/src/test-helpers.d.ts",
55
+ "default": "./build/src/test-helpers.js"
56
+ },
57
+ "./package.json": "./package.json"
58
+ },
59
+ "imports": {
60
+ "#types": "./build/src/types.js"
61
+ },
62
+ "engines": {
63
+ "node": ">=22"
64
+ },
65
+ "scripts": {
66
+ "test": "npm run build && node --test tests/**/*.test.js",
67
+ "lint": "eslint src/ tests/",
68
+ "typecheck": "tsc --noEmit",
69
+ "clean": "node scripts/clean.js",
70
+ "compile": "tsc -b",
71
+ "postcompile": "node scripts/ensure-cli-executable.js",
72
+ "build": "npm run clean && npm run compile",
73
+ "prepare": "npm run build",
74
+ "prepack": "npm run build",
75
+ "check": "npm run lint && npm run typecheck && npm run test",
76
+ "release:patch": "npm version patch && git push --follow-tags",
77
+ "release:minor": "npm version minor && git push --follow-tags",
78
+ "release:major": "npm version major && git push --follow-tags"
79
+ },
80
+ "devDependencies": {
81
+ "@types/node": "^26.1.1",
82
+ "eslint": "^9.39.2",
83
+ "eslint-plugin-jsdoc": "^61.5.0",
84
+ "typescript": "^5.9.3"
85
+ },
86
+ "files": [
87
+ "build",
88
+ "examples",
89
+ "docs",
90
+ "README.md"
91
+ ]
92
+ }