repo-branch 0.0.6 → 0.0.8
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/dist/index.js +93 -106
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -1,143 +1,115 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
-
if (k2 === undefined) k2 = k;
|
|
5
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
3
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
5
|
};
|
|
39
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
7
|
const commander_1 = require("commander");
|
|
41
|
-
const rest_1 = require("@octokit/rest");
|
|
42
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
43
9
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
44
10
|
const listr_1 = __importDefault(require("listr"));
|
|
45
11
|
const dotenv_1 = __importDefault(require("dotenv"));
|
|
46
|
-
const
|
|
47
|
-
const
|
|
12
|
+
const util_1 = require("util");
|
|
13
|
+
const exec = (0, util_1.promisify)(require("child_process").exec);
|
|
48
14
|
// Load environment variables from .env file
|
|
49
15
|
dotenv_1.default.config({ quiet: true });
|
|
50
16
|
const program = new commander_1.Command();
|
|
51
17
|
// Configuration - load from environment variables
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
// Function to validate environment variables
|
|
60
|
-
function validateEnv() {
|
|
61
|
-
if (!GITHUB_OWNER) {
|
|
62
|
-
console.error(chalk_1.default.red("❌ BRANCH_SYNC_GITHUB_OWNER not found in environment variables"));
|
|
63
|
-
console.error(chalk_1.default.yellow("Please set BRANCH_SYNC_GITHUB_OWNER in your .env file or as environment variable"));
|
|
64
|
-
return false;
|
|
18
|
+
const GITHUB_ORG = process.env.BRANCH_SYNC_GITHUB_ORG || "";
|
|
19
|
+
// Get current GitHub user (from gh auth status)
|
|
20
|
+
const getCurrentUser = async () => {
|
|
21
|
+
try {
|
|
22
|
+
const { stdout } = await exec("gh api user --jq .login");
|
|
23
|
+
return stdout.trim();
|
|
65
24
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw new Error("Failed to get GitHub user. Please run 'gh auth login'");
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
// Function to validate environment and get owner
|
|
30
|
+
const validateAndGetOwner = async () => {
|
|
31
|
+
if (GITHUB_ORG) {
|
|
32
|
+
return GITHUB_ORG;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const currentUser = await getCurrentUser();
|
|
36
|
+
return currentUser;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error(chalk_1.default.red("❌ Unable to determine GitHub owner"));
|
|
40
|
+
console.error(chalk_1.default.yellow("Please either:"));
|
|
41
|
+
console.error(chalk_1.default.yellow("1. Set BRANCH_SYNC_GITHUB_ORG in your .env file"));
|
|
42
|
+
console.error(chalk_1.default.yellow("2. Run 'gh auth login' to authenticate with GitHub CLI"));
|
|
43
|
+
throw error;
|
|
70
44
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
console.error(chalk_1.default.yellow("BRANCH_SYNC_GITHUB_TOKEN=your_token_here"));
|
|
78
|
-
console.error(chalk_1.default.yellow("BRANCH_SYNC_GITHUB_OWNER=your_username"));
|
|
45
|
+
};
|
|
46
|
+
// Check if GitHub CLI is installed
|
|
47
|
+
const checkGitHubCLI = async () => {
|
|
48
|
+
try {
|
|
49
|
+
await exec("gh --version");
|
|
50
|
+
return true;
|
|
79
51
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
52
|
+
catch (error) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const getRepositories = async (owner) => {
|
|
84
57
|
try {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
});
|
|
91
|
-
return repos.map((repo) => ({
|
|
58
|
+
const command = `gh repo list ${owner} --limit 1000 --json name,defaultBranchRef,nameWithOwner`;
|
|
59
|
+
const { stdout } = await exec(command);
|
|
60
|
+
const repos = JSON.parse(stdout);
|
|
61
|
+
return repos
|
|
62
|
+
.map((repo) => ({
|
|
92
63
|
name: repo.name,
|
|
93
|
-
defaultBranch: repo.
|
|
94
|
-
|
|
64
|
+
defaultBranch: repo.defaultBranchRef?.name || "main",
|
|
65
|
+
full_name: repo.nameWithOwner,
|
|
66
|
+
}))
|
|
67
|
+
.sort((a, b) => a.full_name.localeCompare(b.full_name));
|
|
95
68
|
}
|
|
96
69
|
catch (error) {
|
|
97
70
|
console.error(chalk_1.default.red("Failed to fetch repositories:"), error);
|
|
98
71
|
throw error;
|
|
99
72
|
}
|
|
100
|
-
}
|
|
101
|
-
async
|
|
73
|
+
};
|
|
74
|
+
const createBranch = async (owner, repoName, branchName) => {
|
|
102
75
|
try {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
ref: `refs/heads/${branchName}`,
|
|
112
|
-
sha: refData.object.sha,
|
|
113
|
-
});
|
|
76
|
+
// Get default branch
|
|
77
|
+
const { stdout: defaultBranchStdout } = await exec(`gh repo view ${owner}/${repoName} --json defaultBranchRef --jq .defaultBranchRef.name`);
|
|
78
|
+
const defaultBranch = defaultBranchStdout.trim() || "main";
|
|
79
|
+
// Get SHA of default branch
|
|
80
|
+
const { stdout: shaStdout } = await exec(`gh api repos/${owner}/${repoName}/git/refs/heads/${defaultBranch} --jq .object.sha`);
|
|
81
|
+
const sha = shaStdout.trim();
|
|
82
|
+
// Create new branch
|
|
83
|
+
await exec(`gh api repos/${owner}/${repoName}/git/refs -f ref=refs/heads/${branchName} -f sha=${sha}`);
|
|
114
84
|
}
|
|
115
85
|
catch (error) {
|
|
116
|
-
if (error.
|
|
86
|
+
if (error.stderr && error.stderr.includes("Reference already exists")) {
|
|
117
87
|
throw new Error(`Branch already exists`);
|
|
118
88
|
}
|
|
119
89
|
throw error;
|
|
120
90
|
}
|
|
121
|
-
}
|
|
122
|
-
async
|
|
91
|
+
};
|
|
92
|
+
const selectRepositories = async (repos) => {
|
|
123
93
|
const answers = await inquirer_1.default.prompt([
|
|
124
94
|
{
|
|
125
95
|
type: "checkbox",
|
|
126
96
|
name: "selectedRepos",
|
|
127
97
|
message: "Select repositories:",
|
|
128
98
|
choices: repos.map((repo) => ({
|
|
129
|
-
name: `${repo.
|
|
99
|
+
name: `${repo.full_name} (${repo.defaultBranch})`,
|
|
130
100
|
value: repo,
|
|
131
101
|
})),
|
|
132
102
|
pageSize: 15,
|
|
133
103
|
},
|
|
134
104
|
]);
|
|
135
105
|
return answers.selectedRepos;
|
|
136
|
-
}
|
|
137
|
-
async
|
|
106
|
+
};
|
|
107
|
+
const run = async (branchName, repoNames) => {
|
|
138
108
|
try {
|
|
139
|
-
|
|
140
|
-
const
|
|
109
|
+
// Get owner (org or current user)
|
|
110
|
+
const owner = await validateAndGetOwner();
|
|
111
|
+
console.log(chalk_1.default.blue(`🔍 Fetching repositories for ${owner}...`));
|
|
112
|
+
const allRepos = await getRepositories(owner);
|
|
141
113
|
let selectedRepos;
|
|
142
114
|
if (repoNames && repoNames.length > 0) {
|
|
143
115
|
selectedRepos = allRepos.filter((repo) => repoNames.includes(repo.name));
|
|
@@ -159,7 +131,7 @@ async function run(branchName, repoNames) {
|
|
|
159
131
|
title: `Creating branch in ${chalk_1.default.cyan(repo.name)}`,
|
|
160
132
|
task: async () => {
|
|
161
133
|
try {
|
|
162
|
-
await createBranch(repo.name, branchName);
|
|
134
|
+
await createBranch(owner, repo.name, branchName);
|
|
163
135
|
}
|
|
164
136
|
catch (error) {
|
|
165
137
|
if (error.message.includes("already exists")) {
|
|
@@ -180,13 +152,28 @@ async function run(branchName, repoNames) {
|
|
|
180
152
|
console.error(chalk_1.default.red("Error:"), error);
|
|
181
153
|
process.exit(1);
|
|
182
154
|
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
program
|
|
155
|
+
};
|
|
156
|
+
// Main execution wrapper to avoid top-level await
|
|
157
|
+
(async () => {
|
|
158
|
+
// Check if GitHub CLI is available
|
|
159
|
+
if (!(await checkGitHubCLI())) {
|
|
160
|
+
console.error(chalk_1.default.red("❌ GitHub CLI not found"));
|
|
161
|
+
console.error(chalk_1.default.yellow("Please install GitHub CLI: https://cli.github.com/"));
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
program
|
|
165
|
+
.name("repo-branch")
|
|
166
|
+
.description("Create a branch across multiple GitHub repositories")
|
|
167
|
+
.argument("<branch-name>", "name of the branch to create")
|
|
168
|
+
.argument("[repositories...]", "repositories to create branch in")
|
|
169
|
+
.helpOption("-h, --help", "Display help for command")
|
|
170
|
+
.addHelpText("after", `
|
|
171
|
+
Examples:
|
|
172
|
+
$ repo-branch feature/new-ui
|
|
173
|
+
$ repo-branch feature/new-ui repo1 repo2
|
|
174
|
+
`)
|
|
175
|
+
.action((branchName, repositories) => {
|
|
176
|
+
run(branchName, repositories);
|
|
177
|
+
});
|
|
178
|
+
program.parse();
|
|
179
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "repo-branch",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Create branches across multiple GitHub repositories simultaneously",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
"start": "node dist/index.js"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@octokit/rest": "^22.0.1",
|
|
34
33
|
"chalk": "^5.6.2",
|
|
35
34
|
"commander": "^14.0.2",
|
|
36
35
|
"dotenv": "^17.2.3",
|