@androbinco/robin-deployment-cli 0.1.0

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/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@androbinco/robin-deployment-cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI tool to fetch deployment template files (Dockerfile and cloudbuild.yml) into your project",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "bin": {
8
+ "robin-deployment": "./src/index.js"
9
+ },
10
+ "files": [
11
+ "src/",
12
+ "README.md"
13
+ ],
14
+ "keywords": [
15
+ "cli",
16
+ "robin",
17
+ "deployment",
18
+ "docker",
19
+ "gcp",
20
+ "templates"
21
+ ],
22
+ "author": "Hernán Mendez / DevOps",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "commander": "^11.0.0",
26
+ "chalk": "^5.3.0",
27
+ "ora": "^7.0.1",
28
+ "fs-extra": "^11.1.1"
29
+ },
30
+ "devDependencies": {
31
+ "nodemon": "^3.0.0"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "scripts": {
37
+ "start": "node ./src/index.js",
38
+ "dev": "node ./src/index.js",
39
+ "test": "echo \"Error: no test specified for robin-deployment-cli\" && exit 1",
40
+ "build": "echo \"robin-deployment-cli: No build step required.\"",
41
+ "lint": "echo \"robin-deployment-cli: Lint not configured.\""
42
+ }
43
+ }
package/src/index.js ADDED
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { program } from 'commander';
4
+ import chalk from 'chalk';
5
+ import ora from 'ora';
6
+ import fs from 'fs-extra';
7
+ import path from 'path';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+ const TEMPLATES_DIR = path.join(__dirname, 'templates');
12
+
13
+
14
+ program
15
+ .name('robin-deployment')
16
+ .description('CLI tool to fetch deployment files (Dockerfile and cloudbuild.yml) into your project')
17
+ .version('0.1.0');
18
+
19
+
20
+ program
21
+ .command('fetch')
22
+ .description('Fetch deployment files into current directory')
23
+ .option('-d, --docker-only', 'Fetch only Dockerfile')
24
+ .option('-g, --gcp-only', 'Fetch only GCP configuration file')
25
+ .option('-p, --path <path>', 'Target directory (default: current directory)', '.')
26
+ .option('-f, --force', 'Overwrite existing files without prompting')
27
+ .action(async (options) => {
28
+ const spinner = ora('Fetching deployment files...').start();
29
+
30
+ try {
31
+ const targetDir = path.resolve(options.path);
32
+
33
+
34
+ await fs.ensureDir(targetDir);
35
+
36
+
37
+ let filesToCopy = [];
38
+ if (options.dockerOnly) {
39
+ filesToCopy = ['Dockerfile'];
40
+ } else if (options.gcpOnly) {
41
+ filesToCopy = ['cloudbuild.yml'];
42
+ } else {
43
+ filesToCopy = ['Dockerfile', 'cloudbuild.yml'];
44
+ }
45
+
46
+
47
+ const existingFiles = [];
48
+ for (const file of filesToCopy) {
49
+ const targetPath = path.join(targetDir, file);
50
+ if (await fs.pathExists(targetPath)) {
51
+ existingFiles.push(file);
52
+ }
53
+ }
54
+
55
+
56
+ if (existingFiles.length > 0 && !options.force) {
57
+ spinner.warn(chalk.yellow(`Found existing files: ${existingFiles.join(', ')}`));
58
+ console.log(chalk.yellow('\nUse --force to overwrite or remove the files manually.'));
59
+ process.exit(1);
60
+ }
61
+
62
+
63
+ let copiedFiles = [];
64
+ for (const file of filesToCopy) {
65
+ const sourcePath = path.join(TEMPLATES_DIR, file);
66
+ const targetPath = path.join(targetDir, file);
67
+
68
+
69
+ if (!await fs.pathExists(sourcePath)) {
70
+ spinner.warn(chalk.yellow(`Template not found: ${file}`));
71
+ continue;
72
+ }
73
+
74
+ await fs.copy(sourcePath, targetPath, { overwrite: options.force });
75
+ copiedFiles.push(file);
76
+ }
77
+
78
+ if (copiedFiles.length === 0) {
79
+ spinner.fail(chalk.red('No files were copied'));
80
+ process.exit(1);
81
+ }
82
+
83
+ spinner.succeed(chalk.green('Deployment files fetched successfully'));
84
+
85
+
86
+ console.log(chalk.blue('\n📁 Files created:'));
87
+ copiedFiles.forEach(file => {
88
+ console.log(chalk.gray(` ✓ ${path.join(targetDir, file)}`));
89
+ });
90
+
91
+
92
+ console.log(chalk.yellow('\n💡 Next steps:'));
93
+ if (copiedFiles.includes('Dockerfile')) {
94
+ console.log(chalk.gray(' • Review and customize the Dockerfile for your project'));
95
+ console.log(chalk.gray(' • Build: docker build -t your-image-name .'));
96
+ }
97
+ if (copiedFiles.includes('cloudbuild.yml')) {
98
+ console.log(chalk.gray(' • Update the variables in cloudbuild.yml'));
99
+ console.log(chalk.gray(' • Deploy: gcloud builds submit'));
100
+ }
101
+
102
+ } catch (error) {
103
+ spinner.fail(chalk.red('Error fetching deployment files'));
104
+ console.error(chalk.red(`\nDetails: ${error.message}`));
105
+ process.exit(1);
106
+ }
107
+ });
108
+
109
+
110
+ program
111
+ .command('list')
112
+ .description('List all available deployment templates')
113
+ .action(async () => {
114
+ try {
115
+ if (!await fs.pathExists(TEMPLATES_DIR)) {
116
+ console.error(chalk.red('\n❌ Templates directory not found'));
117
+ console.log(chalk.yellow('Make sure template files are placed in src/templates/'));
118
+ process.exit(1);
119
+ }
120
+
121
+ const files = await fs.readdir(TEMPLATES_DIR);
122
+
123
+ if (files.length === 0) {
124
+ console.log(chalk.yellow('\n⚠️ No templates found'));
125
+ console.log(chalk.gray('Add your deployment files to src/templates/'));
126
+ return;
127
+ }
128
+
129
+ console.log(chalk.blue('\n📋 Available deployment templates:\n'));
130
+
131
+ for (const file of files) {
132
+ const filePath = path.join(TEMPLATES_DIR, file);
133
+ const stats = await fs.stat(filePath);
134
+ const size = (stats.size / 1024).toFixed(2);
135
+
136
+ console.log(` ${chalk.white('•')} ${chalk.cyan(file)} ${chalk.gray(`(${size} KB)`)}`);
137
+ }
138
+
139
+ console.log(chalk.gray('\nUse "robin-deployment show <template>" to view contents'));
140
+
141
+ } catch (error) {
142
+ console.error(chalk.red('Error listing templates:', error.message));
143
+ process.exit(1);
144
+ }
145
+ });
146
+
147
+ program
148
+ .command('show <template>')
149
+ .description('Show the contents of a specific template')
150
+ .action(async (template) => {
151
+ try {
152
+ const filePath = path.join(TEMPLATES_DIR, template);
153
+
154
+ if (!await fs.pathExists(filePath)) {
155
+ console.error(chalk.red(`\n❌ Template not found: ${template}`));
156
+ console.log(chalk.gray('Use "robin-deployment list" to see available templates'));
157
+ process.exit(1);
158
+ }
159
+
160
+ const content = await fs.readFile(filePath, 'utf-8');
161
+
162
+ console.log(chalk.blue(`\n📄 ${template}:`));
163
+ console.log(chalk.gray('─'.repeat(60)));
164
+ console.log(content);
165
+ console.log(chalk.gray('─'.repeat(60)));
166
+
167
+ } catch (error) {
168
+ console.error(chalk.red('Error showing template:', error.message));
169
+ process.exit(1);
170
+ }
171
+ });
172
+
173
+
174
+ program.parse(process.argv);
175
+
176
+
177
+ if (!process.argv.slice(2).length) {
178
+ program.outputHelp();
179
+ }
@@ -0,0 +1,36 @@
1
+ FROM node:18-alpine AS builder
2
+
3
+ RUN corepack enable && corepack prepare pnpm@latest --activate
4
+
5
+ WORKDIR /app
6
+
7
+ COPY package.json pnpm-lock.yaml ./
8
+
9
+ RUN pnpm install --frozen-lockfile
10
+
11
+ COPY . .
12
+
13
+ RUN mkdir -p src/common/utils src/common/ui
14
+
15
+ RUN pnpm build
16
+
17
+ FROM node:18-alpine AS runner
18
+
19
+ WORKDIR /app
20
+
21
+ RUN corepack enable && corepack prepare pnpm@latest --activate
22
+
23
+ COPY --from=builder /app/package.json /app/pnpm-lock.yaml ./
24
+ COPY --from=builder /app/.next ./.next
25
+ COPY --from=builder /app/public ./public
26
+ COPY --from=builder /app/next.config.ts ./
27
+ COPY --from=builder /app/src ./src
28
+
29
+ RUN pnpm install --prod --frozen-lockfile
30
+
31
+ ENV NODE_ENV=production
32
+ ENV PORT=3000
33
+
34
+ EXPOSE 3000
35
+
36
+ CMD ["pnpm", "start"]
@@ -0,0 +1,22 @@
1
+ steps:
2
+ - name: 'gcr.io/cloud-builders/docker'
3
+ args: ['build', '-t', 'gcr.io/$PROJECT_ID/YOUR_SERVICE_NAME', '.']
4
+
5
+ - name: 'gcr.io/cloud-builders/docker'
6
+ args: ['push', 'gcr.io/$PROJECT_ID/YOUR_SERVICE_NAME']
7
+
8
+ - name: 'gcr.io/cloud-builders/gcloud'
9
+ args:
10
+ - 'run'
11
+ - 'deploy'
12
+ - 'YOUR_SERVICE_NAME'
13
+ - '--image=gcr.io/$PROJECT_ID/YOUR_SERVICE_NAME'
14
+ - '--platform=managed'
15
+ - '--region=us-east1'
16
+ - '--allow-unauthenticated'
17
+ - '--memory=2Gi'
18
+ - '--cpu=4'
19
+ - '--min-instances=1'
20
+ - '--max-instances=3'
21
+ options:
22
+ logging: CLOUD_LOGGING_ONLY