-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSetup , run and push . Yml
More file actions
983 lines (784 loc) · 39 KB
/
Copy pathSetup , run and push . Yml
File metadata and controls
983 lines (784 loc) · 39 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
# Manual dispatch: add this file via the GitHub UI and then run the workflow.
on:
workflow_dispatch:
permissions:
contents: write
jobs:
create-files-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout main
uses: actions/checkout@v4
with:
ref: main
persist-credentials: true
- name: Create files
run: |
set -e
# Top-level files
cat > package.json <<'EOF'
{
"name": "github-app-sample",
"version": "1.0.0",
"description": "Minimal example: authenticate as a GitHub App, call GET /app, list installations and create installation tokens",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"dotenv": "^16.3.1",
"octokit": "^2.0.0",
"@octokit/auth-app": "^4.0.0"
}
}
EOF
cat > index.js <<'EOF'
import 'dotenv/config';
import { Octokit } from "octokit";
import { createAppAuth } from "@octokit/auth-app";
function normalizePrivateKey(raw) {
if (!raw) return raw;
if (raw.includes('\\n')) {
return raw.replace(/\\n/g, '\n');
}
return raw;
}
async function run() {
const { APP_ID, PRIVATE_KEY, INSTALLATION_ID } = process.env;
if (!APP_ID || !PRIVATE_KEY) {
console.error("ERROR: APP_ID and PRIVATE_KEY must be set (see .env.example)");
process.exit(1);
}
const privateKey = normalizePrivateKey(PRIVATE_KEY);
const octokit = new Octokit({
authStrategy: createAppAuth,
auth: {
appId: APP_ID,
privateKey,
},
});
try {
console.log("=== GET /app (App metadata) ===");
const { data: app } = await octokit.request("GET /app", {
headers: {
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28"
}
});
console.log(JSON.stringify(app, null, 2));
console.log("\\n=== GET /app/installations (Installations for this App) ===");
const { data: installations } = await octokit.request("GET /app/installations");
if (!installations || installations.length === 0) {
console.log("No installations found for this app.");
} else {
console.log("Found installations:");
installations.forEach(inst => {
console.log(`- id: ${inst.id}, account: ${inst.account?.login}, app_slug: ${inst.app_slug}`);
});
}
const installationId = INSTALLATION_ID || (installations && installations[0] && installations[0].id);
if (!installationId) {
console.log("\\nNo installation id provided and none found automatically. Set INSTALLATION_ID in .env or choose one from the installations list above.");
return;
}
console.log(`\\n=== Creating installation access token for installation ${installationId} ===`);
const { data: tokenData } = await octokit.request(
"POST /app/installations/{installation_id}/access_tokens",
{ installation_id: installationId }
);
console.log("Installation token created. Expires at:", tokenData.expires_at);
const installationOctokit = new Octokit({ auth: tokenData.token });
const repos = await installationOctokit.request("GET /installation/repositories");
console.log("\\nRepositories visible to this installation:");
repos.data.repositories.forEach(r => {
console.log(`- ${r.full_name}`);
});
} catch (err) {
console.error("Error:", err.message || err);
if (err.status) console.error("HTTP status:", err.status);
if (err.response && err.response.data) {
console.error("Response data:", JSON.stringify(err.response.data, null, 2));
}
process.exit(1);
}
}
run();
EOF
cat > .env.example <<'EOF'
# Copy this file to .env and fill values.
# APP_ID: the numeric App ID shown on your GitHub App settings page (e.g. 12345)
# PRIVATE_KEY: the full PEM private key you download from GitHub when creating the App.
# If you paste it into an environment variable, make sure it contains the newlines.
# INSTALLATION_ID: optional - if provided the script will create an installation token for this id.
APP_ID=12345
# Option A (recommended): put the PEM exactly as downloaded (multi-line).
# Option B: single-line with literal \n sequences (the script converts them):
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nREPLACE_WITH_YOUR_KEY\n-----END RSA PRIVATE KEY-----"
INSTALLATION_ID=
EOF
cat > README.md <<'EOF'
# GitHub App example (Node.js + Octokit)
This small example authenticates as a GitHub App (using the app's private key), calls `GET /app` to fetch app metadata, lists installations, and can create an installation access token to act as that installation.
Quick start
1. Copy `.env.example` to `.env` and fill APP_ID and PRIVATE_KEY (and optionally INSTALLATION_ID).
2. npm install
3. npm start
Security tips
- Keep the private key secret. Do NOT commit `.env` to source control.
- Prefer storing the private key in a secrets manager or environment variables injected at runtime.
EOF
cat > SECURITY.md <<'EOF'
# Security Policy
Thank you for responsibly reporting security issues in MeGaOcToOoN.
Reporting
- Email: security@elmorab3.com (replace with your contact email)
- Please include: steps to reproduce, impact, reproduction code or logs, and suggested mitigation.
Response
- We will acknowledge reports within 72 hours.
- We aim to provide a remediation timeline depending on severity.
Public disclosure
- Please coordinate with us before public disclosure to allow us to address issues.
Notes
- Do NOT send private keys or credentials in any report.
- For urgent incidents, contact: security@elmorab3.com
EOF
cat > INSTALL.md <<'EOF'
# Installing MeGaOcToOoN (quick start)
One-click install link:
- https://github.com/apps/MeGaOcToOoN/installations/new
- Replace `MeGaOcToOoN` with your app slug if different.
Recommended public install flow:
1. User clicks the install link and chooses an account/repositories.
2. GitHub redirects to your Setup URL configured in the GitHub App settings with `installation_id` in the query string.
3. Your server (the setup endpoint) calls GitHub to exchange `installation_id` for an installation access token and completes onboarding (webhook registration, default settings, etc.).
Local dev & testing:
1. Copy `server/.env.example` to `server/.env` and set:
- APP_ID: your numeric GitHub App ID
- PRIVATE_KEY: your PEM private key (do NOT commit)
- SETUP_ORIGIN: your public domain (https://elmorab3.com)
2. In `server/` run:
- npm install
- npm start
3. For local testing of the installation callback, you can use ngrok to expose your local server and set the App Setup URL to the ngrok URL.
Security notes:
- Never commit PRIVATE_KEY to the repository.
- Use GitHub Secrets (APP_ID, PRIVATE_KEY, INSTALLATION_ID) in Actions or a secure secrets manager in production.
EOF
cat > MARKETPLACE.md <<'EOF'
# Marketplace Listing Draft — MeGaOcToOoN
Name: MeGaOcToOoN
Short description:
A lightweight GitHub App that [briefly describe main functionality — metrics, automation, PR helpers, etc.].
Long description:
MeGaOcToOoN helps teams automate [task], integrate with [service], and enforce [policy]. It is built with minimal permissions and focuses on privacy and ease-of-install.
Permissions requested:
- Repositories: Read-only (list repos, metadata)
- Issues: Read & Write (only if creating or updating issues)
- Pull requests: Read-only (unless optional features require write)
- Webhooks: push, pull_request, installation (to respond to installs and events)
Installation/Onboarding:
- One-click install via GitHub.
- Post-install setup URL will automatically complete onboarding: create any required config, register webhooks, and show a success screen.
Support & privacy:
- Support: support@elmorab3.com
- Privacy Policy: https://elmorab3.com/privacy
- Terms: https://elmorab3.com/terms
Assets:
- Logo: 128x128 PNG
- Screenshots: 3 images (install, config, dashboard)
- Category: Developer tools / Automation
Notes for review:
- App requests minimal permissions by default. Any escalated permissions are requested only at explicit consent steps.
- Include a short explainer video and a troubleshooting guide in the listing.
EOF
# Workflows
mkdir -p .github/workflows
cat > .github/workflows/ci.yml <<'EOF'
name: CI / Build / Test
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run tests
env:
APP_ID: ${{ secrets.APP_ID }}
run: npm test
deploy:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
needs: build-and-test
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run deployment script (example)
env:
APP_ID: ${{ secrets.APP_ID }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
INSTALLATION_ID: ${{ secrets.INSTALLATION_ID }} # optional
run: node server/index.js
EOF
cat > .github/workflows/release.yml <<'EOF'
name: Create GitHub Release on tag
on:
push:
tags:
- 'v*' # any tag starting with v, e.g. v10.0
jobs:
create_release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create GitHub Release
uses: ncipollo/release-action@v1
with:
tag: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
EOF
cat > AGENT.md <<'EOF'
name: MeGaOcToOoN Agent
description: A lightweight companion service for the MeGaOcToOoN GitHub App that handles post-install onboarding, installation token exchange, webhook processing, and optional automation tasks. Designed to be run as a small Express server or serverless function and to be deployed with secrets stored in your host's secret manager.
---
# My Agent
This document describes what the MeGaOcToOoN Agent does, how it should be configured, and what to include when committing it to the repository.
## Purpose
The MeGaOcToOoN Agent performs the server-side actions required after a user installs the MeGaOcToOoN GitHub App. Its primary responsibilities are:
- Accept the GitHub App setup redirect and exchange the installation_id for a short-lived installation access token.
- Run onboarding automation (create repo config files, register webhooks, seed data).
- Provide a webhook endpoint to receive and process GitHub events (installation, push, pull_request, etc.).
- Provide a healthcheck and basic status page for monitoring.
## Responsibilities / capabilities
- GET /setup
- Receives `installation_id` from GitHub after the user installs the app.
- Uses the App JWT (created with APP_ID + PRIVATE_KEY) to request an installation token from GitHub.
- Performs onboarding tasks using the installation token and shows a success page.
- POST /webhook
- Receives events from GitHub.
- Validates signature using a webhook secret.
- Routes events to handlers for processing (e.g., create issue, label PR).
- Optional admin endpoints (protected by auth) to list active installations and revoke tokens.
## Run & configure
Environment variables (never commit real values):
- APP_ID — numeric GitHub App ID
- PRIVATE_KEY — PEM for the GitHub App (store in secrets, not repo)
- WEBHOOK_SECRET — secret to validate webhook payloads
- SETUP_ORIGIN — public origin for redirects (e.g. https://elmorab3.com)
- ADMIN_EMAIL — optional admin contact
Example local start:
1. Copy `server/.env.example` → `server/.env` and fill values (do NOT commit).
2. npm install
3. npm start
CI / deployment:
- Store secrets in GitHub Actions secrets or your host provider (Render, Fly, Vercel).
- Use the `.github/workflows/ci.yml` and `release.yml` to run tests and publish releases.
- Ensure PRIVATE_KEY is only available to runtime and CI via secrets.
## Commit & PR guidance (what to add to the repo)
When adding or updating the agent code, use a clear commit message and request a reviewer. Example:
- Commit message: chore(agent): add setup server and agent metadata
- PR title: feat(agent): add setup server and onboarding flow
- Request reviewer: @ELMOURABEA
If you want to indicate collaborative authorship for automation, you may add a co-author trailer in commits:
- Co-authored-by: GitHub Copilot <copilot@github.com>
## Security considerations
- NEVER commit PRIVATE_KEY or other secrets to the repo.
- Validate webhooks using X-Hub-Signature-256 and the webhook secret.
- Restrict app permissions to the minimum required (principle of least privilege).
- Rotate private key periodically and publish a revocation/rotation plan.
- Enable branch protection and require PR reviews for main.
## Review checklist for PRs touching the agent
- [ ] No private keys or secrets are included
- [ ] .env.example present and complete
- [ ] README / INSTALL.md updated with setup URL and domain
- [ ] Tests added or smoke checks for endpoints
- [ ] CI workflow references secrets via \${{ secrets.* }} and does not print them
- [ ] Webhook signature validation implemented
- [ ] Code scanning (CodeQL) passes or is configured
---
Thanks — special thanks to @ELMOURABEA for the opportunity to help finish this project.
Co-authored-by: GitHub Copilot <copilot@github.com>
EOF
cat > RELEASE_NOTES.md <<'EOF'
# Release v10.0 — Release notes template
Summary
- Short summary of the release and the high-level features/fixes.
New
- List major new features introduced in v10.0.
Fixed
- List important bug fixes.
Breaking changes
- Document any breaking changes, migration notes, or configuration changes.
Upgrade notes
- Steps for users to upgrade and any post-upgrade actions (e.g., reconfigure webhook, rotate keys).
Security
- Note any security fixes and guidance (rotate secrets if needed).
Assets
- Attach links to docs, changelog, screenshots, and any relevant migration scripts.
Support
- Contact: support@elmorab3.com
EOF
mkdir -p server
cat > server/package.json <<'EOF'
{
"name": "megaoctooon-setup-server",
"version": "1.0.0",
"description": "Setup server for MeGaOcToOoN GitHub App - handles installation callbacks and creates installation tokens",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js",
"dev": "NODE_ENV=development nodemon index.js"
},
"dependencies": {
"dotenv": "^16.3.1",
"express": "^4.18.2",
"octokit": "^2.0.0",
"@octokit/auth-app": "^4.0.0"
}
}
EOF
cat > server/.env.example <<'EOF'
# Copy to server/.env and fill in values (DO NOT commit .env)
APP_ID=12345
# PRIVATE_KEY: either paste multi-line PEM or single-line with \n sequences (script supports both)
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nREPLACE_WITH_KEY\n-----END RSA PRIVATE KEY-----"
# Public origin where your app runs, used for redirects (e.g. https://elmorab3.com)
SETUP_ORIGIN=https://elmorab3.com
# Optional: a dashboard admin email
ADMIN_EMAIL=admin@elmorab3.com
EOF
cat > server/index.js <<'EOF'
import express from "express";
import 'dotenv/config';
import { Octokit } from "octokit";
import { createAppAuth } from "@octokit/auth-app";
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
function normalizePrivateKey(raw) {
if (!raw) return raw;
if (raw.includes("\\n")) return raw.replace(/\\n/g, "\\n");
return raw;
}
const APP_ID = process.env.APP_ID;
const PRIVATE_KEY = normalizePrivateKey(process.env.PRIVATE_KEY);
if (!APP_ID || !PRIVATE_KEY) {
console.warn("Warning: APP_ID and PRIVATE_KEY should be set in environment for production use.");
}
// Simple healthcheck
app.get("/", (req, res) => res.send("MeGaOcToOoN setup server is running."));
// Setup endpoint — configured as "Setup URL" in GitHub App settings.
// GitHub will redirect here after installation with ?installatname: Create app infra files, commit to main, and tag v10.0
# Manual dispatch: add this file via the GitHub UI and then run the workflow.
on:
workflow_dispatch:
permissions:
contents: write
jobs:
create-files-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout main
uses: actions/checkout@v4
with:
ref: main
persist-credentials: true
- name: Create files
run: |
set -e
# Top-level files
cat > package.json <<'EOF'
{
"name": "github-app-sample",
"version": "1.0.0",
"description": "Minimal example: authenticate as a GitHub App, call GET /app, list installations and create installation tokens",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"dotenv": "^16.3.1",
"octokit": "^2.0.0",
"@octokit/auth-app": "^4.0.0"
}
}
EOF
cat > index.js <<'EOF'
import 'dotenv/config';
import { Octokit } from "octokit";
import { createAppAuth } from "@octokit/auth-app";
function normalizePrivateKey(raw) {
if (!raw) return raw;
if (raw.includes('\\n')) {
return raw.replace(/\\n/g, '\n');
}
return raw;
}
async function run() {
const { APP_ID, PRIVATE_KEY, INSTALLATION_ID } = process.env;
if (!APP_ID || !PRIVATE_KEY) {
console.error("ERROR: APP_ID and PRIVATE_KEY must be set (see .env.example)");
process.exit(1);
}
const privateKey = normalizePrivateKey(PRIVATE_KEY);
const octokit = new Octokit({
authStrategy: createAppAuth,
auth: {
appId: APP_ID,
privateKey,
},
});
try {
console.log("=== GET /app (App metadata) ===");
const { data: app } = await octokit.request("GET /app", {
headers: {
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28"
}
});
console.log(JSON.stringify(app, null, 2));
console.log("\\n=== GET /app/installations (Installations for this App) ===");
const { data: installations } = await octokit.request("GET /app/installations");
if (!installations || installations.length === 0) {
console.log("No installations found for this app.");
} else {
console.log("Found installations:");
installations.forEach(inst => {
console.log(`- id: ${inst.id}, account: ${inst.account?.login}, app_slug: ${inst.app_slug}`);
});
}
const installationId = INSTALLATION_ID || (installations && installations[0] && installations[0].id);
if (!installationId) {
console.log("\\nNo installation id provided and none found automatically. Set INSTALLATION_ID in .env or choose one from the installations list above.");
return;
}
console.log(`\\n=== Creating installation access token for installation ${installationId} ===`);
const { data: tokenData } = await octokit.request(
"POST /app/installations/{installation_id}/access_tokens",
{ installation_id: installationId }
);
console.log("Installation token created. Expires at:", tokenData.expires_at);
const installationOctokit = new Octokit({ auth: tokenData.token });
const repos = await installationOctokit.request("GET /installation/repositories");
console.log("\\nRepositories visible to this installation:");
repos.data.repositories.forEach(r => {
console.log(`- ${r.full_name}`);
});
} catch (err) {
console.error("Error:", err.message || err);
if (err.status) console.error("HTTP status:", err.status);
if (err.response && err.response.data) {
console.error("Response data:", JSON.stringify(err.response.data, null, 2));
}
process.exit(1);
}
}
run();
EOF
cat > .env.example <<'EOF'
# Copy this file to .env and fill values.
# APP_ID: the numeric App ID shown on your GitHub App settings page (e.g. 12345)
# PRIVATE_KEY: the full PEM private key you download from GitHub when creating the App.
# If you paste it into an environment variable, make sure it contains the newlines.
# INSTALLATION_ID: optional - if provided the script will create an installation token for this id.
APP_ID=12345
# Option A (recommended): put the PEM exactly as downloaded (multi-line).
# Option B: single-line with literal \n sequences (the script converts them):
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nREPLACE_WITH_YOUR_KEY\n-----END RSA PRIVATE KEY-----"
INSTALLATION_ID=
EOF
cat > README.md <<'EOF'
# GitHub App example (Node.js + Octokit)
This small example authenticates as a GitHub App (using the app's private key), calls `GET /app` to fetch app metadata, lists installations, and can create an installation access token to act as that installation.
Quick start
1. Copy `.env.example` to `.env` and fill APP_ID and PRIVATE_KEY (and optionally INSTALLATION_ID).
2. npm install
3. npm start
Security tips
- Keep the private key secret. Do NOT commit `.env` to source control.
- Prefer storing the private key in a secrets manager or environment variables injected at runtime.
EOF
cat > SECURITY.md <<'EOF'
# Security Policy
Thank you for responsibly reporting security issues in MeGaOcToOoN.
Reporting
- Email: security@elmorab3.com (replace with your contact email)
- Please include: steps to reproduce, impact, reproduction code or logs, and suggested mitigation.
Response
- We will acknowledge reports within 72 hours.
- We aim to provide a remediation timeline depending on severity.
Public disclosure
- Please coordinate with us before public disclosure to allow us to address issues.
Notes
- Do NOT send private keys or credentials in any report.
- For urgent incidents, contact: security@elmorab3.com
EOF
cat > INSTALL.md <<'EOF'
# Installing MeGaOcToOoN (quick start)
One-click install link:
- https://github.com/apps/MeGaOcToOoN/installations/new
- Replace `MeGaOcToOoN` with your app slug if different.
Recommended public install flow:
1. User clicks the install link and chooses an account/repositories.
2. GitHub redirects to your Setup URL configured in the GitHub App settings with `installation_id` in the query string.
3. Your server (the setup endpoint) calls GitHub to exchange `installation_id` for an installation access token and completes onboarding (webhook registration, default settings, etc.).
Local dev & testing:
1. Copy `server/.env.example` to `server/.env` and set:
- APP_ID: your numeric GitHub App ID
- PRIVATE_KEY: your PEM private key (do NOT commit)
- SETUP_ORIGIN: your public domain (https://elmorab3.com)
2. In `server/` run:
- npm install
- npm start
3. For local testing of the installation callback, you can use ngrok to expose your local server and set the App Setup URL to the ngrok URL.
Security notes:
- Never commit PRIVATE_KEY to the repository.
- Use GitHub Secrets (APP_ID, PRIVATE_KEY, INSTALLATION_ID) in Actions or a secure secrets manager in production.
EOF
cat > MARKETPLACE.md <<'EOF'
# Marketplace Listing Draft — MeGaOcToOoN
Name: MeGaOcToOoN
Short description:
A lightweight GitHub App that [briefly describe main functionality — metrics, automation, PR helpers, etc.].
Long description:
MeGaOcToOoN helps teams automate [task], integrate with [service], and enforce [policy]. It is built with minimal permissions and focuses on privacy and ease-of-install.
Permissions requested:
- Repositories: Read-only (list repos, metadata)
- Issues: Read & Write (only if creating or updating issues)
- Pull requests: Read-only (unless optional features require write)
- Webhooks: push, pull_request, installation (to respond to installs and events)
Installation/Onboarding:
- One-click install via GitHub.
- Post-install setup URL will automatically complete onboarding: create any required config, register webhooks, and show a success screen.
Support & privacy:
- Support: support@elmorab3.com
- Privacy Policy: https://elmorab3.com/privacy
- Terms: https://elmorab3.com/terms
Assets:
- Logo: 128x128 PNG
- Screenshots: 3 images (install, config, dashboard)
- Category: Developer tools / Automation
Notes for review:
- App requests minimal permissions by default. Any escalated permissions are requested only at explicit consent steps.
- Include a short explainer video and a troubleshooting guide in the listing.
EOF
# Workflows
mkdir -p .github/workflows
cat > .github/workflows/ci.yml <<'EOF'
name: CI / Build / Test
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run tests
env:
APP_ID: ${{ secrets.APP_ID }}
run: npm test
deploy:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
needs: build-and-test
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run deployment script (example)
env:
APP_ID: ${{ secrets.APP_ID }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
INSTALLATION_ID: ${{ secrets.INSTALLATION_ID }} # optional
run: node server/index.js
EOF
cat > .github/workflows/release.yml <<'EOF'
name: Create GitHub Release on tag
on:
push:
tags:
- 'v*' # any tag starting with v, e.g. v10.0
jobs:
create_release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create GitHub Release
uses: ncipollo/release-action@v1
with:
tag: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
EOF
cat > AGENT.md <<'EOF'
name: MeGaOcToOoN Agent
description: A lightweight companion service for the MeGaOcToOoN GitHub App that handles post-install onboarding, installation token exchange, webhook processing, and optional automation tasks. Designed to be run as a small Express server or serverless function and to be deployed with secrets stored in your host's secret manager.
---
# My Agent
This document describes what the MeGaOcToOoN Agent does, how it should be configured, and what to include when committing it to the repository.
## Purpose
The MeGaOcToOoN Agent performs the server-side actions required after a user installs the MeGaOcToOoN GitHub App. Its primary responsibilities are:
- Accept the GitHub App setup redirect and exchange the installation_id for a short-lived installation access token.
- Run onboarding automation (create repo config files, register webhooks, seed data).
- Provide a webhook endpoint to receive and process GitHub events (installation, push, pull_request, etc.).
- Provide a healthcheck and basic status page for monitoring.
## Responsibilities / capabilities
- GET /setup
- Receives `installation_id` from GitHub after the user installs the app.
- Uses the App JWT (created with APP_ID + PRIVATE_KEY) to request an installation token from GitHub.
- Performs onboarding tasks using the installation token and shows a success page.
- POST /webhook
- Receives events from GitHub.
- Validates signature using a webhook secret.
- Routes events to handlers for processing (e.g., create issue, label PR).
- Optional admin endpoints (protected by auth) to list active installations and revoke tokens.
## Run & configure
Environment variables (never commit real values):
- APP_ID — numeric GitHub App ID
- PRIVATE_KEY — PEM for the GitHub App (store in secrets, not repo)
- WEBHOOK_SECRET — secret to validate webhook payloads
- SETUP_ORIGIN — public origin for redirects (e.g. https://elmorab3.com)
- ADMIN_EMAIL — optional admin contact
Example local start:
1. Copy `server/.env.example` → `server/.env` and fill values (do NOT commit).
2. npm install
3. npm start
CI / deployment:
- Store secrets in GitHub Actions secrets or your host provider (Render, Fly, Vercel).
- Use the `.github/workflows/ci.yml` and `release.yml` to run tests and publish releases.
- Ensure PRIVATE_KEY is only available to runtime and CI via secrets.
## Commit & PR guidance (what to add to the repo)
When adding or updating the agent code, use a clear commit message and request a reviewer. Example:
- Commit message: chore(agent): add setup server and agent metadata
- PR title: feat(agent): add setup server and onboarding flow
- Request reviewer: @ELMOURABEA
If you want to indicate collaborative authorship for automation, you may add a co-author trailer in commits:
- Co-authored-by: GitHub Copilot <copilot@github.com>
## Security considerations
- NEVER commit PRIVATE_KEY or other secrets to the repo.
- Validate webhooks using X-Hub-Signature-256 and the webhook secret.
- Restrict app permissions to the minimum required (principle of least privilege).
- Rotate private key periodically and publish a revocation/rotation plan.
- Enable branch protection and require PR reviews for main.
## Review checklist for PRs touching the agent
- [ ] No private keys or secrets are included
- [ ] .env.example present and complete
- [ ] README / INSTALL.md updated with setup URL and domain
- [ ] Tests added or smoke checks for endpoints
- [ ] CI workflow references secrets via \${{ secrets.* }} and does not print them
- [ ] Webhook signature validation implemented
- [ ] Code scanning (CodeQL) passes or is configured
---
Thanks — special thanks to @ELMOURABEA for the opportunity to help finish this project.
Co-authored-by: GitHub Copilot <copilot@github.com>
EOF
cat > RELEASE_NOTES.md <<'EOF'
# Release v10.0 — Release notes template
Summary
- Short summary of the release and the high-level features/fixes.
New
- List major new features introduced in v10.0.
Fixed
- List important bug fixes.
Breaking changes
- Document any breaking changes, migration notes, or configuration changes.
Upgrade notes
- Steps for users to upgrade and any post-upgrade actions (e.g., reconfigure webhook, rotate keys).
Security
- Note any security fixes and guidance (rotate secrets if needed).
Assets
- Attach links to docs, changelog, screenshots, and any relevant migration scripts.
Support
- Contact: support@elmorab3.com
EOF
mkdir -p server
cat > server/package.json <<'EOF'
{
"name": "megaoctooon-setup-server",
"version": "1.0.0",
"description": "Setup server for MeGaOcToOoN GitHub App - handles installation callbacks and creates installation tokens",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js",
"dev": "NODE_ENV=development nodemon index.js"
},
"dependencies": {
"dotenv": "^16.3.1",
"express": "^4.18.2",
"octokit": "^2.0.0",
"@octokit/auth-app": "^4.0.0"
}
}
EOF
cat > server/.env.example <<'EOF'
# Copy to server/.env and fill in values (DO NOT commit .env)
APP_ID=12345
# PRIVATE_KEY: either paste multi-line PEM or single-line with \n sequences (script supports both)
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nREPLACE_WITH_KEY\n-----END RSA PRIVATE KEY-----"
# Public origin where your app runs, used for redirects (e.g. https://elmorab3.com)
SETUP_ORIGIN=https://elmorab3.com
# Optional: a dashboard admin email
ADMIN_EMAIL=admin@elmorab3.com
EOF
cat > server/index.js <<'EOF'
import express from "express";
import 'dotenv/config';
import { Octokit } from "octokit";
import { createAppAuth } from "@octokit/auth-app";
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
function normalizePrivateKey(raw) {
if (!raw) return raw;
if (raw.includes("\\n")) return raw.replace(/\\n/g, "\\n");
return raw;
}
const APP_ID = process.env.APP_ID;
const PRIVATE_KEY = normalizePrivateKey(process.env.PRIVATE_KEY);
if (!APP_ID || !PRIVATE_KEY) {
console.warn("Warning: APP_ID and PRIVATE_KEY should be set in environment for production use.");
}
// Simple healthcheck
app.get("/", (req, res) => res.send("MeGaOcToOoN setup server is running."));
// Setup endpoint — configured as "Setup URL" in GitHub App settings.
// GitHub will redirect here after installation with ?installat