-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgithub_sync.ts
More file actions
126 lines (110 loc) · 4.6 KB
/
github_sync.ts
File metadata and controls
126 lines (110 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { Octokit } from '@octokit/rest';
import { execSync } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
let connectionSettings: any;
async function getAccessToken() {
if (connectionSettings && connectionSettings.settings.expires_at && new Date(connectionSettings.settings.expires_at).getTime() > Date.now()) {
return connectionSettings.settings.access_token;
}
const hostname = process.env.REPLIT_CONNECTORS_HOSTNAME;
const xReplitToken = process.env.REPL_IDENTITY
? 'repl ' + process.env.REPL_IDENTITY
: process.env.WEB_REPL_RENEWAL
? 'depl ' + process.env.WEB_REPL_RENEWAL
: null;
if (!xReplitToken) throw new Error('X_REPLIT_TOKEN not found');
connectionSettings = await fetch(
'https://' + hostname + '/api/v2/connection?include_secrets=true&connector_names=github',
{ headers: { 'Accept': 'application/json', 'X_REPLIT_TOKEN': xReplitToken } }
).then(res => res.json()).then(data => data.items?.[0]);
const accessToken = connectionSettings?.settings?.access_token || connectionSettings.settings?.oauth?.credentials?.access_token;
if (!connectionSettings || !accessToken) throw new Error('GitHub not connected');
return accessToken;
}
const OWNER = 'contact219';
const REPO = '444EVER';
const BRANCH = 'main';
const WORKSPACE = '/home/runner/workspace';
const IGNORE = new Set(['.git', 'node_modules', '.cache', '.config', '.local', 'dist', '.replit', 'replit.nix', '.upm', 'generated-icon.png', '.gitignore']);
function getAllFiles(dir: string, baseDir: string): { filePath: string; relativePath: string }[] {
const results: { filePath: string; relativePath: string }[] = [];
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
if (IGNORE.has(entry.name)) continue;
if (entry.name.startsWith('.') && entry.name !== '.gitignore') continue;
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
results.push(...getAllFiles(fullPath, baseDir));
} else {
results.push({ filePath: fullPath, relativePath: path.relative(baseDir, fullPath) });
}
}
return results;
}
async function main() {
const token = await getAccessToken();
const octokit = new Octokit({ auth: token });
console.log('Collecting files...');
const files = getAllFiles(WORKSPACE, WORKSPACE);
console.log(`Found ${files.length} files to sync`);
// Get the current commit SHA on main
let currentSha: string | undefined;
try {
const { data: ref } = await octokit.git.getRef({ owner: OWNER, repo: REPO, ref: `heads/${BRANCH}` });
currentSha = ref.object.sha;
console.log(`Current HEAD: ${currentSha}`);
} catch (e: any) {
console.log('Branch not found, will create new');
}
// Create blobs for all files
console.log('Creating blobs...');
const treeItems: { path: string; mode: '100644'; type: 'blob'; sha: string }[] = [];
const BATCH_SIZE = 10;
for (let i = 0; i < files.length; i += BATCH_SIZE) {
const batch = files.slice(i, i + BATCH_SIZE);
const results = await Promise.all(batch.map(async (f) => {
const content = fs.readFileSync(f.filePath);
const { data } = await octokit.git.createBlob({
owner: OWNER, repo: REPO,
content: content.toString('base64'),
encoding: 'base64',
});
return { path: f.relativePath, mode: '100644' as const, type: 'blob' as const, sha: data.sha };
}));
treeItems.push(...results);
process.stdout.write(` ${Math.min(i + BATCH_SIZE, files.length)}/${files.length} files uploaded\r`);
}
console.log('\nCreating tree...');
// Create tree
const { data: tree } = await octokit.git.createTree({
owner: OWNER, repo: REPO,
tree: treeItems,
});
console.log('Creating commit...');
const commitParams: any = {
owner: OWNER, repo: REPO,
message: 'Sync: Admin dashboard expansion - multi-admin users, segments, automations, reviews, drops, promo analytics',
tree: tree.sha,
};
if (currentSha) commitParams.parents = [currentSha];
const { data: commit } = await octokit.git.createCommit(commitParams);
console.log('Updating branch reference...');
if (currentSha) {
await octokit.git.updateRef({
owner: OWNER, repo: REPO,
ref: `heads/${BRANCH}`,
sha: commit.sha,
force: true,
});
} else {
await octokit.git.createRef({
owner: OWNER, repo: REPO,
ref: `refs/heads/${BRANCH}`,
sha: commit.sha,
});
}
console.log(`\nSuccessfully synced to GitHub!`);
console.log(`Commit: ${commit.sha}`);
console.log(`View at: https://github.com/${OWNER}/${REPO}`);
}
main().catch(err => { console.error('Error:', err.message); process.exit(1); });