@fenwave/agent 1.1.3 → 1.1.5

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/cli-commands.js CHANGED
@@ -127,7 +127,6 @@ function setupCLICommands(program, startServerFunction) {
127
127
  .action(async () => {
128
128
  try {
129
129
  const { loadDeviceCredential, isDeviceRegistered } = await import('./store/deviceCredentialStore.js');
130
- const { hasNpmToken } = await import('./store/npmTokenStore.js');
131
130
 
132
131
  console.log(chalk.bold('\nšŸ“Š Fenwave Agent Status\n'));
133
132
 
@@ -233,7 +232,6 @@ function setupCLICommands(program, startServerFunction) {
233
232
  try {
234
233
  const { getDeviceMetadata } = await import('./utils/deviceInfo.js');
235
234
  const { saveDeviceCredential, isDeviceRegistered } = await import('./store/deviceCredentialStore.js');
236
- const { saveNpmToken } = await import('./store/npmTokenStore.js');
237
235
 
238
236
  // Check if already registered
239
237
  if (isDeviceRegistered()) {
@@ -299,11 +297,6 @@ function setupCLICommands(program, startServerFunction) {
299
297
  agentVersion: deviceMetadata.agentVersion,
300
298
  });
301
299
 
302
- // Save NPM token if provided
303
- if (response.data.npmToken) {
304
- saveNpmToken(response.data.npmToken);
305
- }
306
-
307
300
  spinner.succeed('Device registered successfully');
308
301
  console.log(chalk.green('\nāœ… Registration Complete'));
309
302
  console.log(chalk.gray(` Device ID: ${response.data.deviceId}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenwave/agent",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "Fenwave Docker Agent and CLI",
5
5
  "keywords": [
6
6
  "fenwave",
@@ -0,0 +1,212 @@
1
+ #!/bin/bash
2
+
3
+ # Fenwave Agent Release Script
4
+ # Usage: ./scripts/release.sh [patch|minor|major|x.x.x]
5
+
6
+ set -e
7
+
8
+ # Colors
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ BLUE='\033[0;34m'
13
+ NC='\033[0m' # No Color
14
+
15
+ # Functions
16
+ log_info() { echo -e "${BLUE}ℹ ${NC}$1"; }
17
+ log_success() { echo -e "${GREEN}āœ“ ${NC}$1"; }
18
+ log_warning() { echo -e "${YELLOW}⚠ ${NC}$1"; }
19
+ log_error() { echo -e "${RED}āœ— ${NC}$1"; exit 1; }
20
+
21
+ # Check prerequisites
22
+ check_prerequisites() {
23
+ log_info "Checking prerequisites..."
24
+
25
+ command -v node >/dev/null 2>&1 || log_error "Node.js is required"
26
+ command -v npm >/dev/null 2>&1 || log_error "npm is required"
27
+ command -v gh >/dev/null 2>&1 || log_error "GitHub CLI (gh) is required"
28
+ command -v git >/dev/null 2>&1 || log_error "git is required"
29
+
30
+ # Check if logged into npm
31
+ npm whoami >/dev/null 2>&1 || log_error "Not logged into npm. Run 'npm login' first"
32
+
33
+ # Check if logged into GitHub CLI
34
+ gh auth status >/dev/null 2>&1 || log_error "Not logged into GitHub CLI. Run 'gh auth login' first"
35
+
36
+ # Check for uncommitted changes
37
+ if [[ -n $(git status --porcelain) ]]; then
38
+ log_error "Working directory has uncommitted changes. Commit or stash them first"
39
+ fi
40
+
41
+ # Check we're on main branch
42
+ CURRENT_BRANCH=$(git branch --show-current)
43
+ if [[ "$CURRENT_BRANCH" != "main" ]]; then
44
+ log_warning "Not on main branch (currently on: $CURRENT_BRANCH)"
45
+ read -p "Continue anyway? (y/N) " -n 1 -r
46
+ echo
47
+ [[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
48
+ fi
49
+
50
+ # Pull latest changes
51
+ log_info "Pulling latest changes..."
52
+ git pull origin "$CURRENT_BRANCH"
53
+
54
+ log_success "Prerequisites check passed"
55
+ }
56
+
57
+ # Get version argument
58
+ get_version() {
59
+ VERSION_ARG=$1
60
+ CURRENT_VERSION=$(node -p "require('./package.json').version")
61
+
62
+ if [[ -z "$VERSION_ARG" ]]; then
63
+ echo "" >&2
64
+ echo "Current version: $CURRENT_VERSION" >&2
65
+ echo "" >&2
66
+ echo "Select version bump:" >&2
67
+ echo " 1) patch (x.x.X) - Bug fixes" >&2
68
+ echo " 2) minor (x.X.0) - New features" >&2
69
+ echo " 3) major (X.0.0) - Breaking changes" >&2
70
+ echo " 4) custom - Enter specific version" >&2
71
+ echo "" >&2
72
+ read -p "Choice [1-4]: " choice
73
+
74
+ case $choice in
75
+ 1) VERSION_ARG="patch" ;;
76
+ 2) VERSION_ARG="minor" ;;
77
+ 3) VERSION_ARG="major" ;;
78
+ 4) read -p "Enter version (e.g., 1.2.3): " VERSION_ARG ;;
79
+ *) log_error "Invalid choice" ;;
80
+ esac
81
+ fi
82
+
83
+ echo "$VERSION_ARG"
84
+ }
85
+
86
+ # Bump version
87
+ bump_version() {
88
+ local VERSION_TYPE=$1
89
+
90
+ log_info "Bumping version ($VERSION_TYPE)..." >&2
91
+
92
+ if [[ "$VERSION_TYPE" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
93
+ # Specific version provided
94
+ npm version "$VERSION_TYPE" --no-git-tag-version >/dev/null
95
+ else
96
+ # patch, minor, or major
97
+ npm version "$VERSION_TYPE" --no-git-tag-version >/dev/null
98
+ fi
99
+
100
+ NEW_VERSION=$(node -p "require('./package.json').version")
101
+ log_success "Version bumped to $NEW_VERSION" >&2
102
+
103
+ echo "$NEW_VERSION"
104
+ }
105
+
106
+ # Commit and tag
107
+ commit_and_tag() {
108
+ local VERSION=$1
109
+
110
+ log_info "Committing version bump..."
111
+
112
+ git add package.json package-lock.json 2>/dev/null || git add package.json
113
+ git commit -m "chore: release v$VERSION"
114
+
115
+ log_info "Creating git tag v$VERSION..."
116
+ git tag -a "v$VERSION" -m "Release v$VERSION"
117
+
118
+ log_success "Committed and tagged"
119
+ }
120
+
121
+ # Push to remote
122
+ push_to_remote() {
123
+ local VERSION=$1
124
+
125
+ log_info "Pushing to remote..."
126
+
127
+ git push origin "$(git branch --show-current)"
128
+ git push origin "v$VERSION"
129
+
130
+ log_success "Pushed to remote"
131
+ }
132
+
133
+ # Create GitHub release
134
+ create_github_release() {
135
+ local VERSION=$1
136
+
137
+ log_info "Creating GitHub release..."
138
+
139
+ # Get commits since last tag
140
+ LAST_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
141
+
142
+ if [[ -n "$LAST_TAG" ]]; then
143
+ CHANGES=$(git log "$LAST_TAG"..HEAD --pretty=format:"- %s" --no-merges | grep -v "chore: release")
144
+ else
145
+ CHANGES="- Initial release"
146
+ fi
147
+
148
+ # Create release notes
149
+ RELEASE_NOTES="## What's Changed
150
+
151
+ $CHANGES
152
+
153
+ **Full Changelog**: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/compare/${LAST_TAG:-v0.0.0}...v$VERSION"
154
+
155
+ gh release create "v$VERSION" \
156
+ --title "v$VERSION" \
157
+ --notes "$RELEASE_NOTES"
158
+
159
+ log_success "GitHub release created"
160
+ }
161
+
162
+ # Publish to npm
163
+ publish_to_npm() {
164
+ log_info "Publishing to npm..."
165
+
166
+ # Check if OTP is needed
167
+ read -p "Enter npm OTP (leave empty if not using 2FA): " OTP
168
+
169
+ if [[ -n "$OTP" ]]; then
170
+ npm publish --access public --otp="$OTP"
171
+ else
172
+ npm publish --access public
173
+ fi
174
+
175
+ log_success "Published to npm"
176
+ }
177
+
178
+ # Main
179
+ main() {
180
+ echo ""
181
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
182
+ echo " Fenwave Agent Release Script"
183
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
184
+ echo ""
185
+
186
+ check_prerequisites
187
+
188
+ VERSION_ARG=$(get_version "$1")
189
+ NEW_VERSION=$(bump_version "$VERSION_ARG")
190
+
191
+ echo ""
192
+ log_info "Ready to release v$NEW_VERSION"
193
+ read -p "Continue with release? (y/N) " -n 1 -r
194
+ echo ""
195
+ [[ ! $REPLY =~ ^[Yy]$ ]] && { log_warning "Release cancelled"; exit 0; }
196
+
197
+ commit_and_tag "$NEW_VERSION"
198
+ push_to_remote "$NEW_VERSION"
199
+ create_github_release "$NEW_VERSION"
200
+ publish_to_npm
201
+
202
+ echo ""
203
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
204
+ echo -e "${GREEN} Release v$NEW_VERSION completed successfully!${NC}"
205
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
206
+ echo ""
207
+ echo " npm: https://www.npmjs.com/package/@fenwave/agent"
208
+ echo " GitHub: $(gh repo view --json url -q .url)/releases/tag/v$NEW_VERSION"
209
+ echo ""
210
+ }
211
+
212
+ main "$@"
@@ -29,17 +29,15 @@ import {
29
29
  saveDeviceCredential,
30
30
  isDeviceRegistered,
31
31
  } from "../store/deviceCredentialStore.js";
32
- import { saveNpmToken } from "../store/npmTokenStore.js";
33
32
  import {
34
33
  saveSetupProgress,
35
34
  clearSetupState,
36
35
  SetupStep,
37
36
  isSetupInProgress,
38
37
  } from "../store/setupState.js";
39
- import { authenticateDockerWithECR } from "../utils/ecrAuth.js";
40
38
  import { initializeConfig } from "../store/configStore.js";
41
39
 
42
- const TOTAL_STEPS = 7;
40
+ const TOTAL_STEPS = 5; // Reduced - no ECR auth or NPM config needed (public package and GHCR)
43
41
 
44
42
  /**
45
43
  * Setup Wizard Orchestrator
@@ -49,8 +47,6 @@ export class SetupWizard {
49
47
  constructor(options = {}) {
50
48
  this.backendUrl = options.backendUrl || "http://localhost:7007";
51
49
  this.frontendUrl = options.frontendUrl || "http://localhost:3000";
52
- this.awsRegion = options.awsRegion || "eu-west-1";
53
- this.awsAccountId = options.awsAccountId || null; // Will be set from Backstage during registration
54
50
  this.skipPrerequisites = options.skipPrerequisites || false;
55
51
  this.registrationToken = options.token || null;
56
52
  }
@@ -67,8 +63,6 @@ export class SetupWizard {
67
63
  const agentConfig = {
68
64
  backendUrl: this.backendUrl,
69
65
  frontendUrl: this.frontendUrl,
70
- awsRegion: this.awsRegion,
71
- awsAccountId: this.awsAccountId,
72
66
  };
73
67
 
74
68
  initializeConfig(agentConfig);
@@ -76,10 +70,6 @@ export class SetupWizard {
76
70
  displayInfo("Agent configuration initialized:");
77
71
  displayKeyValue("Backend URL", this.backendUrl);
78
72
  displayKeyValue("Frontend URL", this.frontendUrl);
79
- displayKeyValue("AWS Region", this.awsRegion);
80
- if (this.awsAccountId) {
81
- displayKeyValue("AWS Account ID", this.awsAccountId);
82
- }
83
73
  console.log("");
84
74
 
85
75
  // Check if already registered
@@ -116,19 +106,13 @@ export class SetupWizard {
116
106
  // Step 2: Device Registration
117
107
  const registrationData = await this.registrationStep();
118
108
 
119
- // Step 3: Docker Registry Configuration
120
- await this.dockerRegistryStep(registrationData);
121
-
122
- // Step 4: Pull DevApp Image
109
+ // Step 3: Pull DevApp Image (GHCR is public, no auth required)
123
110
  await this.pullImageStep(registrationData);
124
111
 
125
- // Step 5: NPM Configuration
126
- await this.npmConfigStep(registrationData);
127
-
128
- // Step 6: Start Agent (optional)
112
+ // Step 4: Start Agent (optional)
129
113
  await this.startAgentStep();
130
114
 
131
- // Step 7: Complete
115
+ // Step 5: Complete
132
116
  this.displayComplete(registrationData);
133
117
 
134
118
  // Clear setup state
@@ -266,7 +250,6 @@ export class SetupWizard {
266
250
  return {
267
251
  deviceId: response.data.deviceId,
268
252
  deviceCredential: response.data.deviceCredential,
269
- npmToken: response.data.npmToken,
270
253
  registryConfig: response.data.registryConfig,
271
254
  userEntityRef: response.data.userEntityRef || "unknown",
272
255
  };
@@ -288,73 +271,10 @@ export class SetupWizard {
288
271
  }
289
272
 
290
273
  /**
291
- * Step 3: Docker Registry Configuration
292
- */
293
- async dockerRegistryStep(registrationData) {
294
- displayStep(3, TOTAL_STEPS, "Docker Registry Configuration");
295
-
296
- const shouldConfigure = await promptConfirmation(
297
- "Configure AWS ECR for Fenwave images?",
298
- true
299
- );
300
-
301
- if (!shouldConfigure) {
302
- displayInfo("Skipping Docker registry configuration");
303
- saveSetupProgress(SetupStep.DOCKER_REGISTRY, { skipped: true });
304
- return;
305
- }
306
-
307
- const { awsRegion, awsAccountId } = registrationData.registryConfig;
308
-
309
- displayInfo(`Authenticating with AWS ECR (${awsRegion})...`);
310
- displayInfo(
311
- "šŸ” Using Backstage-controlled credential flow (temporary credentials)"
312
- );
313
-
314
- try {
315
- // Use Backstage-controlled credential flow
316
- const authResult = await authenticateDockerWithECR(this.backendUrl);
317
-
318
- displaySuccess("AWS ECR authenticated successfully");
319
- displayInfo(`āœ… Credentials expire at: ${authResult.expiration}`);
320
- displayInfo(`šŸ“¦ Registry: ${authResult.registryUri}`);
321
-
322
- saveSetupProgress(SetupStep.DOCKER_REGISTRY, {
323
- awsRegion: authResult.region,
324
- awsAccountId: authResult.accountId,
325
- registryUri: authResult.registryUri,
326
- expiration: authResult.expiration,
327
- });
328
- } catch (error) {
329
- displayError("Failed to authenticate with AWS ECR");
330
- displayError(`Error: ${error.message}`);
331
- displayWarning(
332
- "Make sure your device is registered and Backstage is running"
333
- );
334
-
335
- const shouldContinue = await promptConfirmation(
336
- "Continue without ECR authentication?",
337
- true
338
- );
339
- if (!shouldContinue) {
340
- throw createError(
341
- ErrorCode.ECR_AUTH_FAILED,
342
- "ECR authentication failed"
343
- );
344
- }
345
-
346
- saveSetupProgress(SetupStep.DOCKER_REGISTRY, {
347
- failed: true,
348
- error: error.message,
349
- });
350
- }
351
- }
352
-
353
- /**
354
- * Step 4: Pull Fenwave DevApp Image
274
+ * Step 3: Pull Fenwave DevApp Image (GHCR is public, no auth required)
355
275
  */
356
276
  async pullImageStep(registrationData) {
357
- displayStep(4, TOTAL_STEPS, "Pull Fenwave DevApp Image");
277
+ displayStep(3, TOTAL_STEPS, "Pull Fenwave DevApp Image");
358
278
 
359
279
  const shouldPull = await promptConfirmation(
360
280
  "Pull Fenwave DevApp Docker image?",
@@ -412,28 +332,10 @@ export class SetupWizard {
412
332
  }
413
333
 
414
334
  /**
415
- * Step 5: NPM Configuration
416
- */
417
- async npmConfigStep(registrationData) {
418
- displayStep(5, TOTAL_STEPS, "NPM Configuration");
419
-
420
- const { npmToken } = registrationData;
421
-
422
- if (npmToken) {
423
- saveNpmToken(npmToken);
424
- displaySuccess("NPM token configured for future updates");
425
- saveSetupProgress(SetupStep.NPM_CONFIG, { configured: true });
426
- } else {
427
- displayWarning("No NPM token provided by backend");
428
- saveSetupProgress(SetupStep.NPM_CONFIG, { configured: false });
429
- }
430
- }
431
-
432
- /**
433
- * Step 6: Start Agent (optional)
335
+ * Step 4: Start Agent (optional)
434
336
  */
435
337
  async startAgentStep() {
436
- displayStep(6, TOTAL_STEPS, "Start Agent Service");
338
+ displayStep(4, TOTAL_STEPS, "Start Agent Service");
437
339
 
438
340
  const shouldStart = await promptConfirmation("Start the agent now?", true);
439
341
 
@@ -453,7 +355,7 @@ export class SetupWizard {
453
355
  * Display completion message
454
356
  */
455
357
  displayComplete(registrationData) {
456
- displayStep(7, TOTAL_STEPS, "Setup Complete! šŸŽ‰");
358
+ displayStep(5, TOTAL_STEPS, "Setup Complete! šŸŽ‰");
457
359
 
458
360
  console.log("");
459
361
  displayHeader("Setup Summary");