@apso/cli 0.26.2 → 0.27.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.
@@ -18,6 +18,11 @@ export default class Deploy extends BaseCommand {
18
18
  * git and push straight to GitHub.
19
19
  */
20
20
  private syncCodeToGithub;
21
- /** Let the user pick one of their GitHub repos to deploy from. */
22
- private promptRepoSelection;
21
+ /**
22
+ * Decide which GitHub repo to deploy to. No local git or `gh` needed to make
23
+ * one — we create it through the user's Apso GitHub connection. Headless (or
24
+ * when the account has no repos) auto-creates a repo named after the service;
25
+ * interactive offers "create new" first, then existing repos.
26
+ */
27
+ private resolveRepo;
23
28
  }
@@ -168,7 +168,7 @@ class Deploy extends base_command_1.default {
168
168
  }
169
169
  let repoFullName = git.localRepoFullName(cwd) || service.githubRepo || repoFlag;
170
170
  if (!repoFullName) {
171
- repoFullName = await this.promptRepoSelection(conn.connectionId);
171
+ repoFullName = await this.resolveRepo(conn.connectionId, service);
172
172
  }
173
173
  // Connect the repo to the service (records ServiceRepository) unless the
174
174
  // service is already linked to this exact repo.
@@ -190,21 +190,49 @@ class Deploy extends base_command_1.default {
190
190
  this.error(`git push to ${repoFullName} failed. Ensure you have push access and your git credentials are set up.\n${msg}`);
191
191
  }
192
192
  }
193
- /** Let the user pick one of their GitHub repos to deploy from. */
194
- async promptRepoSelection(connectionId) {
195
- const repos = await services_1.githubApi.listRepos("", { connectionId, pageSize: 100 });
196
- if (!repos.data.length) {
197
- this.error("No GitHub repositories available. Create one on GitHub (or pass --repo owner/name).");
193
+ /**
194
+ * Decide which GitHub repo to deploy to. No local git or `gh` needed to make
195
+ * one — we create it through the user's Apso GitHub connection. Headless (or
196
+ * when the account has no repos) auto-creates a repo named after the service;
197
+ * interactive offers "create new" first, then existing repos.
198
+ */
199
+ async resolveRepo(connectionId, service) {
200
+ const repoName = (service.name || service.slug).trim();
201
+ const repos = await services_1.githubApi
202
+ .listRepos("", { connectionId, pageSize: 100 })
203
+ .catch(() => ({ data: [] }));
204
+ // Headless, or nothing to pick from: create a repo for this service.
205
+ if (!(0, interactive_1.isInteractive)() || repos.data.length === 0) {
206
+ this.log(`Creating GitHub repository "${repoName}"...`);
207
+ const created = await services_1.githubApi.createRepo(connectionId, repoName, {
208
+ autoInit: false,
209
+ });
210
+ this.log(`Created ${created.fullName}`);
211
+ return created.fullName;
198
212
  }
213
+ // Interactive with existing repos: "create new" first, then the list.
199
214
  const inquirer = await Promise.resolve().then(() => tslib_1.__importStar(require("inquirer")));
215
+ const CREATE = "create";
200
216
  const { repo } = await inquirer.default.prompt([
201
217
  {
202
218
  type: "list",
203
219
  name: "repo",
204
- message: "Select a GitHub repository to deploy from:",
205
- choices: repos.data.map((r) => ({ name: r.fullName, value: r.fullName })),
220
+ message: "Deploy to which GitHub repository?",
221
+ choices: [
222
+ { name: `+ Create new repo "${repoName}"`, value: CREATE },
223
+ new inquirer.default.Separator(),
224
+ ...repos.data.map((r) => ({ name: r.fullName, value: r.fullName })),
225
+ ],
206
226
  },
207
227
  ]);
228
+ if (repo === CREATE) {
229
+ this.log(`Creating GitHub repository "${repoName}"...`);
230
+ const created = await services_1.githubApi.createRepo(connectionId, repoName, {
231
+ autoInit: false,
232
+ });
233
+ this.log(`Created ${created.fullName}`);
234
+ return created.fullName;
235
+ }
208
236
  return repo;
209
237
  }
210
238
  }
@@ -110,6 +110,15 @@ export declare const githubApi: {
110
110
  getConnectUrl(_workspaceSlug: string): Promise<{
111
111
  url: string;
112
112
  }>;
113
+ /**
114
+ * Create a new GitHub repo for a service via the user's connection (no local
115
+ * git or gh required). autoInit=false leaves it empty so the deploy's first
116
+ * push becomes the initial commit.
117
+ */
118
+ createRepo(connectionId: string, serviceName: string, options?: {
119
+ private?: boolean;
120
+ autoInit?: boolean;
121
+ }): Promise<GitHubRepo>;
113
122
  /** Link an existing GitHub repo to a service. */
114
123
  connectRepo(serviceId: string, connectionId: string, repoFullName: string): Promise<Raw>;
115
124
  /** Push the service's saved (S3) code to its connected GitHub repo. */
@@ -323,6 +323,30 @@ exports.githubApi = {
323
323
  async getConnectUrl(_workspaceSlug) {
324
324
  return client_1.api.get("/api/github/authorize");
325
325
  },
326
+ /**
327
+ * Create a new GitHub repo for a service via the user's connection (no local
328
+ * git or gh required). autoInit=false leaves it empty so the deploy's first
329
+ * push becomes the initial commit.
330
+ */
331
+ async createRepo(connectionId, serviceName, options) {
332
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
333
+ const raw = await client_1.api.post("/api/github/repos", {
334
+ connectionId,
335
+ serviceName,
336
+ isPrivate: (_a = options === null || options === void 0 ? void 0 : options.private) !== null && _a !== void 0 ? _a : true,
337
+ autoInit: (_b = options === null || options === void 0 ? void 0 : options.autoInit) !== null && _b !== void 0 ? _b : false,
338
+ });
339
+ const r = (_d = (_c = raw === null || raw === void 0 ? void 0 : raw.repository) !== null && _c !== void 0 ? _c : raw === null || raw === void 0 ? void 0 : raw.data) !== null && _d !== void 0 ? _d : raw;
340
+ return {
341
+ id: r.id,
342
+ fullName: (_f = (_e = r.full_name) !== null && _e !== void 0 ? _e : r.fullName) !== null && _f !== void 0 ? _f : r.name,
343
+ name: r.name,
344
+ owner: (_h = (_g = r.owner) === null || _g === void 0 ? void 0 : _g.login) !== null && _h !== void 0 ? _h : r.owner,
345
+ private: Boolean(r.private),
346
+ defaultBranch: (_k = (_j = r.default_branch) !== null && _j !== void 0 ? _j : r.defaultBranch) !== null && _k !== void 0 ? _k : "main",
347
+ url: (_l = r.html_url) !== null && _l !== void 0 ? _l : r.url,
348
+ };
349
+ },
326
350
  /** Link an existing GitHub repo to a service. */
327
351
  async connectRepo(serviceId, connectionId, repoFullName) {
328
352
  return client_1.api.post("/api/github/connect-repo", {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@apso/cli",
3
- "version": "0.26.2",
3
+ "version": "0.27.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@apso/cli",
9
- "version": "0.26.2",
9
+ "version": "0.27.0",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@biomejs/biome": "^1.9.4",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.26.2",
2
+ "version": "0.27.0",
3
3
  "commands": {
4
4
  "config": {
5
5
  "id": "config",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apso/cli",
3
- "version": "0.26.2",
3
+ "version": "0.27.0",
4
4
  "mcpName": "io.github.apsoai/apso",
5
5
  "description": "Apso CLI",
6
6
  "author": "Apso by Mavric - @mavric",