@kaikybrofc/omnizap-system 2.1.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/.env.example +534 -0
- package/LICENSE +21 -0
- package/README.md +431 -0
- package/RELEASE-v2.1.2.md +83 -0
- package/app/config/adminIdentity.js +87 -0
- package/app/config/baileysConfig.js +693 -0
- package/app/config/groupUtils.js +388 -0
- package/app/connection/socketController.js +992 -0
- package/app/controllers/messageController.js +354 -0
- package/app/modules/adminModule/groupCommandHandlers.js +1294 -0
- package/app/modules/adminModule/groupEventHandlers.js +355 -0
- package/app/modules/aiModule/catCommand.js +1006 -0
- package/app/modules/broadcastModule/noticeCommand.js +416 -0
- package/app/modules/gameModule/diceCommand.js +67 -0
- package/app/modules/menuModule/common.js +311 -0
- package/app/modules/menuModule/menus.js +59 -0
- package/app/modules/playModule/playCommand.js +1615 -0
- package/app/modules/quoteModule/quoteCommand.js +851 -0
- package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +786 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.js +2082 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.test.js +760 -0
- package/app/modules/rpgPokemonModule/rpgEvolutionUtils.js +22 -0
- package/app/modules/rpgPokemonModule/rpgPokemonCommand.js +172 -0
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +192 -0
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.test.js +93 -0
- package/app/modules/rpgPokemonModule/rpgPokemonEvolution.test.js +46 -0
- package/app/modules/rpgPokemonModule/rpgPokemonMessages.js +746 -0
- package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1859 -0
- package/app/modules/rpgPokemonModule/rpgPokemonService.js +6738 -0
- package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +354 -0
- package/app/modules/statsModule/globalRankingCommand.js +65 -0
- package/app/modules/statsModule/noMessageCommand.js +288 -0
- package/app/modules/statsModule/rankingCommand.js +60 -0
- package/app/modules/statsModule/rankingCommon.js +889 -0
- package/app/modules/stickerModule/addStickerMetadata.js +239 -0
- package/app/modules/stickerModule/convertToWebp.js +390 -0
- package/app/modules/stickerModule/stickerCommand.js +454 -0
- package/app/modules/stickerModule/stickerConvertCommand.js +156 -0
- package/app/modules/stickerModule/stickerTextCommand.js +657 -0
- package/app/modules/stickerPackModule/autoPackCollectorRuntime.js +20 -0
- package/app/modules/stickerPackModule/autoPackCollectorService.js +284 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.js +466 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +88 -0
- package/app/modules/stickerPackModule/semanticThemeClusterService.js +571 -0
- package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +449 -0
- package/app/modules/stickerPackModule/stickerAssetRepository.js +400 -0
- package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +180 -0
- package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +4078 -0
- package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +598 -0
- package/app/modules/stickerPackModule/stickerClassificationService.js +588 -0
- package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +102 -0
- package/app/modules/stickerPackModule/stickerPackCatalogHttp.js +7506 -0
- package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +1095 -0
- package/app/modules/stickerPackModule/stickerPackEngagementRepository.js +108 -0
- package/app/modules/stickerPackModule/stickerPackErrors.js +30 -0
- package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +110 -0
- package/app/modules/stickerPackModule/stickerPackItemRepository.js +440 -0
- package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +337 -0
- package/app/modules/stickerPackModule/stickerPackMessageService.js +296 -0
- package/app/modules/stickerPackModule/stickerPackRepository.js +442 -0
- package/app/modules/stickerPackModule/stickerPackService.js +788 -0
- package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +51 -0
- package/app/modules/stickerPackModule/stickerPackUtils.js +97 -0
- package/app/modules/stickerPackModule/stickerStorageService.js +507 -0
- package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +233 -0
- package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +205 -0
- package/app/modules/systemMetricsModule/pingCommand.js +421 -0
- package/app/modules/tiktokModule/tiktokCommand.js +798 -0
- package/app/modules/userModule/userCommand.js +1217 -0
- package/app/modules/waifuPicsModule/waifuPicsCommand.js +177 -0
- package/app/observability/metrics.js +734 -0
- package/app/services/captchaService.js +492 -0
- package/app/services/dbWriteQueue.js +572 -0
- package/app/services/groupMetadataService.js +279 -0
- package/app/services/lidMapService.js +663 -0
- package/app/services/messagePersistenceService.js +56 -0
- package/app/services/newsBroadcastService.js +351 -0
- package/app/services/pokeApiService.js +398 -0
- package/app/services/queueUtils.js +57 -0
- package/app/services/socketState.js +7 -0
- package/app/store/aiPromptStore.js +38 -0
- package/app/store/groupConfigStore.js +58 -0
- package/app/store/premiumUserStore.js +36 -0
- package/app/utils/antiLink/antiLinkModule.js +804 -0
- package/app/utils/http/getImageBufferModule.js +18 -0
- package/app/utils/json/jsonSanitizer.js +113 -0
- package/app/utils/json/jsonSanitizer.test.js +40 -0
- package/app/utils/logger/loggerModule.js +262 -0
- package/app/utils/systemMetrics/systemMetricsModule.js +91 -0
- package/database/index.js +2052 -0
- package/database/init.js +516 -0
- package/database/migrations/20260203_0001_sticker_packs.sql +54 -0
- package/database/migrations/20260210_0003_rpg_pokemon.sql +58 -0
- package/database/migrations/20260210_0004_rpg_shiny_biome.sql +9 -0
- package/database/migrations/20260210_0005_rpg_missions.sql +14 -0
- package/database/migrations/20260210_0006_rpg_world_pokedex_traits.sql +27 -0
- package/database/migrations/20260210_0007_rpg_raid_pvp.sql +56 -0
- package/database/migrations/20260210_0008_rpg_social_system.sql +195 -0
- package/database/migrations/20260211_0009_rpg_social_xp.sql +36 -0
- package/database/migrations/20260222_0010_remove_message_xp.sql +2 -0
- package/database/migrations/20260226_0011_sticker_asset_classification.sql +17 -0
- package/database/migrations/20260226_0012_sticker_pack_engagement.sql +16 -0
- package/database/migrations/20260226_0013_sticker_marketplace_intelligence.sql +19 -0
- package/database/migrations/20260226_0014_sticker_pack_publish_flow.sql +30 -0
- package/database/migrations/20260226_0014_sticker_worker_queues.sql +42 -0
- package/database/migrations/20260226_0015_sticker_auto_pack_curation_integrity.sql +18 -0
- package/database/migrations/20260226_0016_sticker_web_google_auth_persistence.sql +34 -0
- package/database/migrations/20260226_0017_sticker_web_admin_ban.sql +22 -0
- package/database/migrations/20260226_0018_sticker_web_admin_moderator.sql +18 -0
- package/database/migrations/20260227_0019_sticker_classification_v2_signals.sql +12 -0
- package/database/migrations/20260227_0020_semantic_theme_clusters.sql +35 -0
- package/docker-compose.yml +103 -0
- package/ecosystem.prod.config.cjs +35 -0
- package/eslint.config.js +61 -0
- package/index.js +437 -0
- package/ml/clip_classifier/Dockerfile +16 -0
- package/ml/clip_classifier/README.md +120 -0
- package/ml/clip_classifier/adaptive_scoring.py +40 -0
- package/ml/clip_classifier/classifier.py +654 -0
- package/ml/clip_classifier/embedding_store.py +481 -0
- package/ml/clip_classifier/env_loader.py +15 -0
- package/ml/clip_classifier/llm_label_expander.py +144 -0
- package/ml/clip_classifier/main.py +213 -0
- package/ml/clip_classifier/requirements.txt +10 -0
- package/ml/clip_classifier/similarity_engine.py +74 -0
- package/observability/alert-rules.yml +60 -0
- package/observability/grafana/dashboards/omnizap-mysql.json +136 -0
- package/observability/grafana/dashboards/omnizap-overview.json +170 -0
- package/observability/grafana/provisioning/dashboards/dashboards.yml +11 -0
- package/observability/grafana/provisioning/datasources/datasources.yml +15 -0
- package/observability/loki-config.yml +38 -0
- package/observability/mysql-exporter.cnf +5 -0
- package/observability/mysql-setup.sql +46 -0
- package/observability/prometheus.yml +32 -0
- package/observability/promtail-config.yml +84 -0
- package/package.json +109 -0
- package/public/api-docs/index.html +144 -0
- package/public/css/github-project-panel.css +297 -0
- package/public/css/stickers-admin.css +1272 -0
- package/public/css/styles.css +671 -0
- package/public/index.html +1311 -0
- package/public/js/apps/apiDocsApp.js +310 -0
- package/public/js/apps/createPackApp.js +2069 -0
- package/public/js/apps/homeApp.js +396 -0
- package/public/js/apps/stickersAdminApp.js +1744 -0
- package/public/js/apps/stickersApp.js +4830 -0
- package/public/js/catalog.js +1019 -0
- package/public/js/github-panel/components/CommitList.js +34 -0
- package/public/js/github-panel/components/ErrorState.js +16 -0
- package/public/js/github-panel/components/GithubProjectPanel.js +106 -0
- package/public/js/github-panel/components/ReleaseList.js +38 -0
- package/public/js/github-panel/components/SkeletonPanel.js +22 -0
- package/public/js/github-panel/components/StatCard.js +15 -0
- package/public/js/github-panel/index.js +15 -0
- package/public/js/github-panel/useGithubRepoData.js +154 -0
- package/public/js/github-panel/vendor/react.js +11 -0
- package/public/js/runtime/react-runtime.js +19 -0
- package/public/licenca/index.html +106 -0
- package/public/stickers/admin/index.html +23 -0
- package/public/stickers/create/index.html +47 -0
- package/public/stickers/index.html +48 -0
- package/public/termos-de-uso/index.html +125 -0
- package/scripts/cache-bust.mjs +107 -0
- package/scripts/deploy.sh +458 -0
- package/scripts/github-deploy-notify.mjs +174 -0
- package/scripts/release.sh +129 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-BR">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Termos de Uso | OmniZap System</title>
|
|
7
|
+
<meta name="description" content="Termos de Uso da plataforma OmniZap System." />
|
|
8
|
+
<meta name="robots" content="index, follow" />
|
|
9
|
+
<link rel="canonical" href="https://omnizap.shop/termos-de-uso/" />
|
|
10
|
+
<link rel="icon" type="image/jpeg" href="https://iili.io/FC3FABe.jpg" />
|
|
11
|
+
<link rel="apple-touch-icon" href="https://iili.io/FC3FABe.jpg" />
|
|
12
|
+
<style>
|
|
13
|
+
:root {
|
|
14
|
+
--bg: #0b1020;
|
|
15
|
+
--bg-2: #121a2f;
|
|
16
|
+
--line: #2a3b60;
|
|
17
|
+
--text: #e6edf7;
|
|
18
|
+
--muted: #9fb0cc;
|
|
19
|
+
--card: #141e36cc;
|
|
20
|
+
}
|
|
21
|
+
* { box-sizing: border-box; }
|
|
22
|
+
body {
|
|
23
|
+
margin: 0;
|
|
24
|
+
font-family: "Manrope", system-ui, -apple-system, sans-serif;
|
|
25
|
+
color: var(--text);
|
|
26
|
+
background:
|
|
27
|
+
radial-gradient(58rem 24rem at -8% -12%, #22c55e26, transparent 60%),
|
|
28
|
+
radial-gradient(58rem 24rem at 112% -10%, #38bdf822, transparent 58%),
|
|
29
|
+
linear-gradient(165deg, var(--bg), var(--bg-2));
|
|
30
|
+
}
|
|
31
|
+
.wrap { width: min(960px, 92vw); margin: 0 auto; padding: 24px 0 42px; }
|
|
32
|
+
.top {
|
|
33
|
+
display: flex;
|
|
34
|
+
gap: 10px;
|
|
35
|
+
flex-wrap: wrap;
|
|
36
|
+
margin-bottom: 16px;
|
|
37
|
+
}
|
|
38
|
+
.top a {
|
|
39
|
+
color: var(--text);
|
|
40
|
+
text-decoration: none;
|
|
41
|
+
border: 1px solid var(--line);
|
|
42
|
+
border-radius: 10px;
|
|
43
|
+
padding: 8px 12px;
|
|
44
|
+
background: #111a2d;
|
|
45
|
+
}
|
|
46
|
+
.card {
|
|
47
|
+
border: 1px solid var(--line);
|
|
48
|
+
border-radius: 14px;
|
|
49
|
+
background: var(--card);
|
|
50
|
+
padding: 18px;
|
|
51
|
+
margin-bottom: 12px;
|
|
52
|
+
}
|
|
53
|
+
h1, h2 { margin: 0 0 10px; }
|
|
54
|
+
h1 { font-size: clamp(28px, 4.2vw, 38px); }
|
|
55
|
+
h2 { font-size: 20px; margin-top: 8px; }
|
|
56
|
+
p, li { color: var(--muted); line-height: 1.6; }
|
|
57
|
+
a { color: #8ec5ff; }
|
|
58
|
+
ul { margin: 0; padding-left: 18px; }
|
|
59
|
+
.updated { color: #bcd1ef; font-size: 14px; }
|
|
60
|
+
</style>
|
|
61
|
+
</head>
|
|
62
|
+
<body>
|
|
63
|
+
<main class="wrap">
|
|
64
|
+
<nav class="top" aria-label="Navegação">
|
|
65
|
+
<a href="/">Início</a>
|
|
66
|
+
<a href="/stickers/">Stickers</a>
|
|
67
|
+
<a href="/api-docs/">API</a>
|
|
68
|
+
<a href="/licenca/">Licença</a>
|
|
69
|
+
</nav>
|
|
70
|
+
|
|
71
|
+
<section class="card">
|
|
72
|
+
<h1>Termos de Uso</h1>
|
|
73
|
+
<p class="updated">Última atualização: 26/02/2026</p>
|
|
74
|
+
<p>Ao acessar e utilizar o OmniZap System, você concorda com estes termos.</p>
|
|
75
|
+
</section>
|
|
76
|
+
|
|
77
|
+
<section class="card">
|
|
78
|
+
<h2>1. Uso da plataforma</h2>
|
|
79
|
+
<ul>
|
|
80
|
+
<li>Você pode usar o sistema para automação e integração com WhatsApp conforme a legislação aplicável.</li>
|
|
81
|
+
<li>É proibido uso para spam, fraude, abuso, engenharia social ou atividades ilícitas.</li>
|
|
82
|
+
<li>Você é responsável pelo conteúdo e pelos comandos enviados por sua operação.</li>
|
|
83
|
+
<li>Ao adicionar o bot em grupos, você reconhece que as mensagens e interações do grupo podem ser processadas para funcionamento dos comandos e recursos do sistema.</li>
|
|
84
|
+
</ul>
|
|
85
|
+
</section>
|
|
86
|
+
|
|
87
|
+
<section class="card">
|
|
88
|
+
<h2>2. API e disponibilidade</h2>
|
|
89
|
+
<ul>
|
|
90
|
+
<li>A API pública pode sofrer limites, manutenção e mudanças de versão sem aviso prévio.</li>
|
|
91
|
+
<li>Não há garantia de disponibilidade contínua ou desempenho mínimo específico.</li>
|
|
92
|
+
</ul>
|
|
93
|
+
</section>
|
|
94
|
+
|
|
95
|
+
<section class="card">
|
|
96
|
+
<h2>3. Conteúdo e stickers</h2>
|
|
97
|
+
<ul>
|
|
98
|
+
<li>Você deve possuir direitos sobre os arquivos enviados e compartilhados.</li>
|
|
99
|
+
<li>Conteúdos que violem direitos autorais ou políticas aplicáveis podem ser removidos.</li>
|
|
100
|
+
</ul>
|
|
101
|
+
</section>
|
|
102
|
+
|
|
103
|
+
<section class="card">
|
|
104
|
+
<h2>4. Dados e privacidade</h2>
|
|
105
|
+
<ul>
|
|
106
|
+
<li>Para operar comandos, estatísticas e organização de packs, o sistema pode coletar e processar dados técnicos e operacionais (como identificadores, mensagens usadas em comandos, metadados de mídia e registros de uso).</li>
|
|
107
|
+
<li>Esses dados são utilizados para funcionamento, segurança, manutenção e melhoria do serviço.</li>
|
|
108
|
+
<li>Ao usar o bot, você concorda com esse tratamento de informações para as finalidades acima.</li>
|
|
109
|
+
</ul>
|
|
110
|
+
<p>Se você deseja solicitar remoção de dados, entre em contato com o administrador:</p>
|
|
111
|
+
<p><a href="https://wa.me/559591122954?text=Ol%C3%A1%2C%20gostaria%20de%20solicitar%20a%20remo%C3%A7%C3%A3o%20dos%20meus%20dados%20do%20OmniZap%20System." target="_blank" rel="noreferrer noopener">Falar com o administrador no WhatsApp</a></p>
|
|
112
|
+
</section>
|
|
113
|
+
|
|
114
|
+
<section class="card">
|
|
115
|
+
<h2>5. Limitação de responsabilidade</h2>
|
|
116
|
+
<p>O OmniZap System é fornecido como está. Não nos responsabilizamos por perdas indiretas, interrupções, bloqueios de conta, danos operacionais ou uso inadequado do sistema por terceiros.</p>
|
|
117
|
+
</section>
|
|
118
|
+
|
|
119
|
+
<section class="card">
|
|
120
|
+
<h2>6. Alterações destes termos</h2>
|
|
121
|
+
<p>Podemos atualizar este documento periodicamente. O uso contínuo da plataforma após alterações representa concordância com os termos vigentes.</p>
|
|
122
|
+
</section>
|
|
123
|
+
</main>
|
|
124
|
+
</body>
|
|
125
|
+
</html>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
const usage = () => {
|
|
7
|
+
console.error('Uso: node scripts/cache-bust.mjs --dir <diretorio> --version <build_id>');
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const parseArgs = (argv) => {
|
|
11
|
+
const options = {
|
|
12
|
+
dir: '',
|
|
13
|
+
version: '',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
17
|
+
const token = argv[index];
|
|
18
|
+
if (token === '--dir') {
|
|
19
|
+
options.dir = String(argv[index + 1] || '');
|
|
20
|
+
index += 1;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (token === '--version') {
|
|
24
|
+
options.version = String(argv[index + 1] || '');
|
|
25
|
+
index += 1;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return options;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const listHtmlFiles = async (rootDir) => {
|
|
34
|
+
const output = [];
|
|
35
|
+
const stack = [rootDir];
|
|
36
|
+
|
|
37
|
+
while (stack.length > 0) {
|
|
38
|
+
const current = stack.pop();
|
|
39
|
+
const entries = await fs.readdir(current, { withFileTypes: true });
|
|
40
|
+
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
const absolutePath = path.join(current, entry.name);
|
|
43
|
+
if (entry.isDirectory()) {
|
|
44
|
+
stack.push(absolutePath);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (entry.isFile() && absolutePath.toLowerCase().endsWith('.html')) {
|
|
48
|
+
output.push(absolutePath);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return output;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const withVersion = (assetPath, version) => {
|
|
57
|
+
const [withoutHash, hash = ''] = assetPath.split('#', 2);
|
|
58
|
+
const [pathname, query = ''] = withoutHash.split('?', 2);
|
|
59
|
+
const params = new URLSearchParams(query);
|
|
60
|
+
params.set('v', version);
|
|
61
|
+
const queryString = params.toString();
|
|
62
|
+
return `${pathname}?${queryString}${hash ? `#${hash}` : ''}`;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const applyCacheBustToHtml = (html, version) => {
|
|
66
|
+
const pattern = /((?:src|href)=["'])(\/(?:js|css)\/[^"']+)(["'])/gi;
|
|
67
|
+
let referencesUpdated = 0;
|
|
68
|
+
|
|
69
|
+
const output = html.replace(pattern, (fullMatch, prefix, assetPath, suffix) => {
|
|
70
|
+
const nextPath = withVersion(assetPath, version);
|
|
71
|
+
if (nextPath !== assetPath) referencesUpdated += 1;
|
|
72
|
+
return `${prefix}${nextPath}${suffix}`;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return { output, referencesUpdated };
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const main = async () => {
|
|
79
|
+
const options = parseArgs(process.argv.slice(2));
|
|
80
|
+
|
|
81
|
+
if (!options.dir || !options.version) {
|
|
82
|
+
usage();
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const targetDir = path.resolve(options.dir);
|
|
87
|
+
const htmlFiles = await listHtmlFiles(targetDir);
|
|
88
|
+
let filesUpdated = 0;
|
|
89
|
+
let referencesUpdated = 0;
|
|
90
|
+
|
|
91
|
+
for (const filePath of htmlFiles) {
|
|
92
|
+
const current = await fs.readFile(filePath, 'utf8');
|
|
93
|
+
const { output, referencesUpdated: fileRefs } = applyCacheBustToHtml(current, options.version);
|
|
94
|
+
if (output !== current) {
|
|
95
|
+
await fs.writeFile(filePath, output, 'utf8');
|
|
96
|
+
filesUpdated += 1;
|
|
97
|
+
referencesUpdated += fileRefs;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
console.log(`[cache-bust] version=${options.version} files=${filesUpdated} refs=${referencesUpdated}`);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
main().catch((error) => {
|
|
105
|
+
console.error(`[cache-bust] erro: ${error?.message || error}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
SOURCE_DIR="${DEPLOY_SOURCE_DIR:-$PROJECT_ROOT/public}"
|
|
6
|
+
DEPLOY_DIR="${DEPLOY_TARGET_DIR:-/var/www/omnizap}"
|
|
7
|
+
BACKUP_ENABLED="${DEPLOY_CREATE_BACKUP:-1}"
|
|
8
|
+
BACKUP_DIR="${DEPLOY_BACKUP_DIR:-$DEPLOY_DIR/.backup}"
|
|
9
|
+
NGINX_SERVICE="${DEPLOY_NGINX_SERVICE:-nginx}"
|
|
10
|
+
RESTART_PM2="${DEPLOY_RESTART_PM2:-1}"
|
|
11
|
+
PM2_APP_NAME="${DEPLOY_PM2_APP_NAME:-omnizap-system-production}"
|
|
12
|
+
BUILD_ID="${DEPLOY_BUILD_ID:-$(date -u +%Y%m%d%H%M%S)}"
|
|
13
|
+
VERIFY_URL="${DEPLOY_VERIFY_URL:-https://omnizap.shop/}"
|
|
14
|
+
DRY_RUN="${DEPLOY_DRY_RUN:-0}"
|
|
15
|
+
GITHUB_NOTIFY="${DEPLOY_GITHUB_NOTIFY:-1}"
|
|
16
|
+
GITHUB_ENVIRONMENT="${DEPLOY_GITHUB_ENVIRONMENT:-production}"
|
|
17
|
+
GITHUB_DEPLOYMENT_ID=""
|
|
18
|
+
PACKAGE_STEP="${DEPLOY_PACKAGE_STEP:-0}"
|
|
19
|
+
PACKAGE_INSTALL="${DEPLOY_PACKAGE_INSTALL:-1}"
|
|
20
|
+
PACKAGE_TEST="${DEPLOY_PACKAGE_TEST:-0}"
|
|
21
|
+
PACKAGE_PACK="${DEPLOY_PACKAGE_PACK:-0}"
|
|
22
|
+
PACKAGE_ARTIFACTS_DIR="${DEPLOY_PACKAGE_ARTIFACTS_DIR:-$PROJECT_ROOT/.artifacts}"
|
|
23
|
+
PACKAGE_PUBLISH="${DEPLOY_PACKAGE_PUBLISH:-0}"
|
|
24
|
+
PACKAGE_PUBLISH_SKIP_IF_EXISTS="${DEPLOY_PACKAGE_PUBLISH_SKIP_IF_EXISTS:-1}"
|
|
25
|
+
PACKAGE_REGISTRY="${DEPLOY_PACKAGE_REGISTRY:-https://npm.pkg.github.com}"
|
|
26
|
+
PACKAGE_TAG="${DEPLOY_PACKAGE_TAG:-latest}"
|
|
27
|
+
PACKAGE_TOKEN="${DEPLOY_PACKAGE_TOKEN:-}"
|
|
28
|
+
PACKAGE_OTP="${DEPLOY_PACKAGE_OTP:-}"
|
|
29
|
+
PACKAGE_PUBLISH_SECONDARY="${DEPLOY_PACKAGE_PUBLISH_SECONDARY:-0}"
|
|
30
|
+
PACKAGE_SECONDARY_REGISTRY="${DEPLOY_PACKAGE_SECONDARY_REGISTRY:-https://registry.npmjs.org}"
|
|
31
|
+
PACKAGE_SECONDARY_TAG="${DEPLOY_PACKAGE_SECONDARY_TAG:-latest}"
|
|
32
|
+
PACKAGE_SECONDARY_TOKEN="${DEPLOY_PACKAGE_SECONDARY_TOKEN:-}"
|
|
33
|
+
PACKAGE_SECONDARY_OTP="${DEPLOY_PACKAGE_SECONDARY_OTP:-}"
|
|
34
|
+
PACKAGE_SECONDARY_ACCESS="${DEPLOY_PACKAGE_SECONDARY_ACCESS:-public}"
|
|
35
|
+
PACKAGE_SECONDARY_PUBLISH_SKIP_IF_EXISTS="${DEPLOY_PACKAGE_SECONDARY_PUBLISH_SKIP_IF_EXISTS:-$PACKAGE_PUBLISH_SKIP_IF_EXISTS}"
|
|
36
|
+
PACKAGE_SECONDARY_TOKEN_KEYS="${DEPLOY_PACKAGE_SECONDARY_TOKEN_KEYS:-}"
|
|
37
|
+
NPMRC_TMP_FILES=()
|
|
38
|
+
|
|
39
|
+
log() {
|
|
40
|
+
printf '[deploy] %s\n' "$*"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
resolve_github_repo() {
|
|
44
|
+
local explicit_repo="${DEPLOY_GITHUB_REPO:-${GITHUB_REPOSITORY:-}}"
|
|
45
|
+
if [ -n "$explicit_repo" ] && printf '%s' "$explicit_repo" | grep -q '/'; then
|
|
46
|
+
printf '%s' "$explicit_repo"
|
|
47
|
+
return 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
local remote_url=""
|
|
51
|
+
remote_url="$(cd "$PROJECT_ROOT" && git config --get remote.origin.url 2>/dev/null || true)"
|
|
52
|
+
if [ -z "$remote_url" ]; then
|
|
53
|
+
return 0
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
local repo=""
|
|
57
|
+
repo="$(printf '%s' "$remote_url" | sed -nE 's#.*github\.com[:/]([^/]+/[^/.]+)(\.git)?$#\1#p' | head -n 1)"
|
|
58
|
+
if [ -n "$repo" ]; then
|
|
59
|
+
printf '%s' "$repo"
|
|
60
|
+
fi
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
resolve_github_owner() {
|
|
64
|
+
local repo=""
|
|
65
|
+
repo="$(resolve_github_repo)"
|
|
66
|
+
if [ -z "$repo" ]; then
|
|
67
|
+
return 0
|
|
68
|
+
fi
|
|
69
|
+
printf '%s' "$repo" | cut -d'/' -f1
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
require_cmd() {
|
|
73
|
+
if ! command -v "$1" >/dev/null 2>&1; then
|
|
74
|
+
printf '[deploy] comando ausente: %s\n' "$1" >&2
|
|
75
|
+
exit 1
|
|
76
|
+
fi
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
resolve_token_from_dotenv() {
|
|
80
|
+
local token_keys="$1"
|
|
81
|
+
if [ -z "$token_keys" ]; then
|
|
82
|
+
return 0
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
(
|
|
86
|
+
cd "$PROJECT_ROOT" && TOKEN_KEYS="$token_keys" node --input-type=module -e "
|
|
87
|
+
import dotenv from 'dotenv';
|
|
88
|
+
dotenv.config({ path: '.env' });
|
|
89
|
+
const keys = String(process.env.TOKEN_KEYS || '')
|
|
90
|
+
.split(',')
|
|
91
|
+
.map((item) => item.trim())
|
|
92
|
+
.filter(Boolean);
|
|
93
|
+
for (const key of keys) {
|
|
94
|
+
const value = process.env[key];
|
|
95
|
+
if (value && String(value).trim()) {
|
|
96
|
+
process.stdout.write(String(value).trim());
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
" 2>/dev/null || true
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
default_token_keys_for_registry() {
|
|
105
|
+
local registry="$1"
|
|
106
|
+
if printf '%s' "$registry" | grep -q 'npm.pkg.github.com'; then
|
|
107
|
+
printf 'DEPLOY_PACKAGE_TOKEN,DEPLOY_GITHUB_TOKEN,GITHUB_TOKEN,GH_TOKEN,NPM_TOKEN,NODE_AUTH_TOKEN'
|
|
108
|
+
else
|
|
109
|
+
printf 'DEPLOY_PACKAGE_SECONDARY_TOKEN,NPM_TOKEN,NODE_AUTH_TOKEN'
|
|
110
|
+
fi
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
create_npmrc_for_registry() {
|
|
114
|
+
local registry="$1"
|
|
115
|
+
local token="$2"
|
|
116
|
+
local scope_owner="$3"
|
|
117
|
+
local registry_host=""
|
|
118
|
+
registry_host="$(printf '%s' "$registry" | sed -E 's#^https?://##; s#/*$##')"
|
|
119
|
+
|
|
120
|
+
local npmrc_tmp=""
|
|
121
|
+
npmrc_tmp="$(mktemp /tmp/omnizap-npmrc.XXXXXX)"
|
|
122
|
+
{
|
|
123
|
+
printf 'registry=%s\n' "$registry"
|
|
124
|
+
if [ -n "$scope_owner" ]; then
|
|
125
|
+
printf '@%s:registry=%s\n' "$scope_owner" "$registry"
|
|
126
|
+
fi
|
|
127
|
+
printf '//%s/:_authToken=%s\n' "$registry_host" "$token"
|
|
128
|
+
printf '//%s:_authToken=%s\n' "$registry_host" "$token"
|
|
129
|
+
} > "$npmrc_tmp"
|
|
130
|
+
chmod 600 "$npmrc_tmp"
|
|
131
|
+
NPMRC_TMP_FILES+=("$npmrc_tmp")
|
|
132
|
+
printf '%s' "$npmrc_tmp"
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
publish_package_to_registry() {
|
|
136
|
+
local pkg_name="$1"
|
|
137
|
+
local pkg_version="$2"
|
|
138
|
+
local registry="$3"
|
|
139
|
+
local tag="$4"
|
|
140
|
+
local explicit_token="$5"
|
|
141
|
+
local skip_if_exists="$6"
|
|
142
|
+
local access="$7"
|
|
143
|
+
local token_keys_override="$8"
|
|
144
|
+
local otp="$9"
|
|
145
|
+
|
|
146
|
+
local token="$explicit_token"
|
|
147
|
+
if [ -z "$token" ]; then
|
|
148
|
+
local token_keys="$token_keys_override"
|
|
149
|
+
if [ -z "$token_keys" ]; then
|
|
150
|
+
token_keys="$(default_token_keys_for_registry "$registry")"
|
|
151
|
+
fi
|
|
152
|
+
token="$(resolve_token_from_dotenv "$token_keys")"
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
if [ -z "$token" ]; then
|
|
156
|
+
printf '[deploy] Publish habilitado para %s, mas nenhum token foi encontrado.\n' "$registry" >&2
|
|
157
|
+
exit 1
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
if printf '%s' "$registry" | grep -q 'registry.npmjs.org'; then
|
|
161
|
+
if printf '%s' "$token" | grep -Eq '^(ghp_|gho_|ghu_|ghs_|ghr_|github_pat_)'; then
|
|
162
|
+
printf '[deploy] Token incompatível para npmjs.org (parece token do GitHub).\n' >&2
|
|
163
|
+
printf '[deploy] Configure DEPLOY_PACKAGE_SECONDARY_TOKEN ou NPM_TOKEN com token do npmjs.\n' >&2
|
|
164
|
+
exit 1
|
|
165
|
+
fi
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
local scope_owner=""
|
|
169
|
+
scope_owner="$(printf '%s' "$pkg_name" | sed -nE 's#^@([^/]+)/.*#\1#p')"
|
|
170
|
+
local pkg_base_name=""
|
|
171
|
+
pkg_base_name="$(printf '%s' "$pkg_name" | sed -E 's#^@[^/]+/##')"
|
|
172
|
+
|
|
173
|
+
if printf '%s' "$registry" | grep -q 'npm.pkg.github.com'; then
|
|
174
|
+
if ! printf '%s' "$pkg_name" | grep -q '^@'; then
|
|
175
|
+
printf '[deploy] Para GitHub Packages o nome do pacote deve ser escopado (ex: @owner/repo).\n' >&2
|
|
176
|
+
exit 1
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
local expected_owner="${DEPLOY_PACKAGE_SCOPE_OWNER:-}"
|
|
180
|
+
if [ -z "$expected_owner" ]; then
|
|
181
|
+
expected_owner="$(resolve_github_owner)"
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
if [ -n "$expected_owner" ] && [ -n "$scope_owner" ] && [ "$scope_owner" != "$expected_owner" ]; then
|
|
185
|
+
printf '[deploy] Scope do pacote (%s) difere do owner GitHub esperado (%s).\n' "$scope_owner" "$expected_owner" >&2
|
|
186
|
+
printf '[deploy] Ajuste com: npm pkg set name=\"@%s/%s\"\n' "$expected_owner" "$pkg_base_name" >&2
|
|
187
|
+
printf '[deploy] Ou defina DEPLOY_PACKAGE_SCOPE_OWNER para publicar em outro owner.\n' >&2
|
|
188
|
+
exit 1
|
|
189
|
+
fi
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
local npmrc_tmp=""
|
|
193
|
+
npmrc_tmp="$(create_npmrc_for_registry "$registry" "$token" "$scope_owner")"
|
|
194
|
+
|
|
195
|
+
if ! (
|
|
196
|
+
cd "$PROJECT_ROOT" &&
|
|
197
|
+
npm_config_userconfig="$npmrc_tmp" npm whoami --registry "$registry" --userconfig "$npmrc_tmp" >/dev/null 2>&1
|
|
198
|
+
); then
|
|
199
|
+
printf '[deploy] Falha de autenticação no registry %s. Verifique token/permissões.\n' "$registry" >&2
|
|
200
|
+
exit 1
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
if [ "$skip_if_exists" = "1" ]; then
|
|
204
|
+
if (
|
|
205
|
+
cd "$PROJECT_ROOT" &&
|
|
206
|
+
npm_config_userconfig="$npmrc_tmp" npm view "${pkg_name}@${pkg_version}" --registry "$registry" --userconfig "$npmrc_tmp" >/dev/null 2>&1
|
|
207
|
+
); then
|
|
208
|
+
log "Pacote ${pkg_name}@${pkg_version} já publicado em $registry (skip)."
|
|
209
|
+
return 0
|
|
210
|
+
fi
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
log "Publicando ${pkg_name}@${pkg_version} em $registry (tag=$tag)"
|
|
214
|
+
local publish_cmd=(npm publish --registry "$registry" --tag "$tag" --userconfig "$npmrc_tmp")
|
|
215
|
+
if [ -n "$access" ] && printf '%s' "$registry" | grep -q 'registry.npmjs.org' && printf '%s' "$pkg_name" | grep -q '^@'; then
|
|
216
|
+
publish_cmd+=(--access "$access")
|
|
217
|
+
fi
|
|
218
|
+
if [ -n "$otp" ]; then
|
|
219
|
+
publish_cmd+=(--otp "$otp")
|
|
220
|
+
fi
|
|
221
|
+
(
|
|
222
|
+
cd "$PROJECT_ROOT" &&
|
|
223
|
+
npm_config_userconfig="$npmrc_tmp" "${publish_cmd[@]}"
|
|
224
|
+
)
|
|
225
|
+
log "Publish concluído para ${pkg_name}@${pkg_version} em $registry."
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
as_root() {
|
|
229
|
+
if [ "$(id -u)" -eq 0 ]; then
|
|
230
|
+
"$@"
|
|
231
|
+
return
|
|
232
|
+
fi
|
|
233
|
+
|
|
234
|
+
if command -v sudo >/dev/null 2>&1; then
|
|
235
|
+
sudo "$@"
|
|
236
|
+
return
|
|
237
|
+
fi
|
|
238
|
+
|
|
239
|
+
printf '[deploy] precisa de root/sudo para executar: %s\n' "$*" >&2
|
|
240
|
+
exit 1
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
require_cmd node
|
|
244
|
+
require_cmd rsync
|
|
245
|
+
require_cmd nginx
|
|
246
|
+
require_cmd systemctl
|
|
247
|
+
|
|
248
|
+
if [ ! -d "$SOURCE_DIR" ]; then
|
|
249
|
+
printf '[deploy] pasta de origem não encontrada: %s\n' "$SOURCE_DIR" >&2
|
|
250
|
+
exit 1
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
STAGING_DIR="$(mktemp -d /tmp/omnizap-deploy.XXXXXX)"
|
|
254
|
+
|
|
255
|
+
github_deploy_start() {
|
|
256
|
+
if [ "$DRY_RUN" = "1" ] || [ "$GITHUB_NOTIFY" != "1" ]; then
|
|
257
|
+
return 0
|
|
258
|
+
fi
|
|
259
|
+
|
|
260
|
+
local deployment_id=""
|
|
261
|
+
deployment_id="$(
|
|
262
|
+
node "$PROJECT_ROOT/scripts/github-deploy-notify.mjs" start \
|
|
263
|
+
--build-id "$BUILD_ID" \
|
|
264
|
+
--environment "$GITHUB_ENVIRONMENT" \
|
|
265
|
+
--environment-url "$VERIFY_URL" \
|
|
266
|
+
--log-url "$VERIFY_URL" 2>/dev/null || true
|
|
267
|
+
)"
|
|
268
|
+
deployment_id="$(printf '%s' "$deployment_id" | tr -d '[:space:]')"
|
|
269
|
+
|
|
270
|
+
if [ -n "$deployment_id" ]; then
|
|
271
|
+
GITHUB_DEPLOYMENT_ID="$deployment_id"
|
|
272
|
+
log "GitHub deployment iniciado: id=$GITHUB_DEPLOYMENT_ID"
|
|
273
|
+
else
|
|
274
|
+
log "GitHub deployment não iniciado (token/repo ausente ou API indisponível)."
|
|
275
|
+
fi
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
github_deploy_status() {
|
|
279
|
+
local state="$1"
|
|
280
|
+
if [ -z "$GITHUB_DEPLOYMENT_ID" ] || [ "$GITHUB_NOTIFY" != "1" ]; then
|
|
281
|
+
return 0
|
|
282
|
+
fi
|
|
283
|
+
|
|
284
|
+
if node "$PROJECT_ROOT/scripts/github-deploy-notify.mjs" status \
|
|
285
|
+
--deployment-id "$GITHUB_DEPLOYMENT_ID" \
|
|
286
|
+
--state "$state" \
|
|
287
|
+
--build-id "$BUILD_ID" \
|
|
288
|
+
--environment "$GITHUB_ENVIRONMENT" \
|
|
289
|
+
--environment-url "$VERIFY_URL" \
|
|
290
|
+
--log-url "$VERIFY_URL" >/dev/null 2>&1; then
|
|
291
|
+
log "GitHub deployment atualizado: id=$GITHUB_DEPLOYMENT_ID state=$state"
|
|
292
|
+
else
|
|
293
|
+
log "Aviso: falha ao atualizar status do deployment no GitHub (state=$state)."
|
|
294
|
+
fi
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
run_package_stage() {
|
|
298
|
+
if [ "$DRY_RUN" = "1" ] || [ "$PACKAGE_STEP" != "1" ]; then
|
|
299
|
+
return 0
|
|
300
|
+
fi
|
|
301
|
+
|
|
302
|
+
require_cmd npm
|
|
303
|
+
|
|
304
|
+
local pkg_version="n/d"
|
|
305
|
+
pkg_version="$(cd "$PROJECT_ROOT" && npm pkg get version 2>/dev/null | tr -d '"[:space:]' || true)"
|
|
306
|
+
log "Etapa package iniciada (versão=$pkg_version)."
|
|
307
|
+
|
|
308
|
+
if [ "$PACKAGE_INSTALL" = "1" ]; then
|
|
309
|
+
if [ -f "$PROJECT_ROOT/package-lock.json" ]; then
|
|
310
|
+
log "Instalando dependências com npm ci --omit=dev"
|
|
311
|
+
(cd "$PROJECT_ROOT" && npm ci --omit=dev)
|
|
312
|
+
else
|
|
313
|
+
log "Instalando dependências com npm install --omit=dev"
|
|
314
|
+
(cd "$PROJECT_ROOT" && npm install --omit=dev)
|
|
315
|
+
fi
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
if [ "$PACKAGE_TEST" = "1" ]; then
|
|
319
|
+
log "Executando testes de package (npm test)"
|
|
320
|
+
(cd "$PROJECT_ROOT" && npm test)
|
|
321
|
+
fi
|
|
322
|
+
|
|
323
|
+
if [ "$PACKAGE_PACK" = "1" ]; then
|
|
324
|
+
log "Gerando artefato npm pack"
|
|
325
|
+
mkdir -p "$PACKAGE_ARTIFACTS_DIR"
|
|
326
|
+
local pack_name=""
|
|
327
|
+
pack_name="$(cd "$PROJECT_ROOT" && npm pack --silent)"
|
|
328
|
+
if [ -n "$pack_name" ] && [ -f "$PROJECT_ROOT/$pack_name" ]; then
|
|
329
|
+
mv "$PROJECT_ROOT/$pack_name" "$PACKAGE_ARTIFACTS_DIR/$pack_name"
|
|
330
|
+
log "Artefato salvo em $PACKAGE_ARTIFACTS_DIR/$pack_name"
|
|
331
|
+
fi
|
|
332
|
+
fi
|
|
333
|
+
|
|
334
|
+
if [ "$PACKAGE_PUBLISH" = "1" ] || [ "$PACKAGE_PUBLISH_SECONDARY" = "1" ]; then
|
|
335
|
+
local pkg_name=""
|
|
336
|
+
pkg_name="$(cd "$PROJECT_ROOT" && npm pkg get name 2>/dev/null | tr -d '"[:space:]' || true)"
|
|
337
|
+
if [ -z "$pkg_name" ] || [ -z "$pkg_version" ] || [ "$pkg_version" = "n/d" ]; then
|
|
338
|
+
printf '[deploy] não foi possível ler nome/versão do package para publish.\n' >&2
|
|
339
|
+
exit 1
|
|
340
|
+
fi
|
|
341
|
+
|
|
342
|
+
if [ "$PACKAGE_PUBLISH" = "1" ]; then
|
|
343
|
+
publish_package_to_registry \
|
|
344
|
+
"$pkg_name" \
|
|
345
|
+
"$pkg_version" \
|
|
346
|
+
"$PACKAGE_REGISTRY" \
|
|
347
|
+
"$PACKAGE_TAG" \
|
|
348
|
+
"$PACKAGE_TOKEN" \
|
|
349
|
+
"$PACKAGE_PUBLISH_SKIP_IF_EXISTS" \
|
|
350
|
+
"" \
|
|
351
|
+
"" \
|
|
352
|
+
"$PACKAGE_OTP"
|
|
353
|
+
fi
|
|
354
|
+
|
|
355
|
+
if [ "$PACKAGE_PUBLISH_SECONDARY" = "1" ]; then
|
|
356
|
+
if [ "$PACKAGE_PUBLISH" = "1" ] && [ "$PACKAGE_SECONDARY_REGISTRY" = "$PACKAGE_REGISTRY" ] && [ "$PACKAGE_SECONDARY_TAG" = "$PACKAGE_TAG" ]; then
|
|
357
|
+
log "Registry/tag secundário igual ao primário. Publish secundário ignorado."
|
|
358
|
+
else
|
|
359
|
+
publish_package_to_registry \
|
|
360
|
+
"$pkg_name" \
|
|
361
|
+
"$pkg_version" \
|
|
362
|
+
"$PACKAGE_SECONDARY_REGISTRY" \
|
|
363
|
+
"$PACKAGE_SECONDARY_TAG" \
|
|
364
|
+
"$PACKAGE_SECONDARY_TOKEN" \
|
|
365
|
+
"$PACKAGE_SECONDARY_PUBLISH_SKIP_IF_EXISTS" \
|
|
366
|
+
"$PACKAGE_SECONDARY_ACCESS" \
|
|
367
|
+
"$PACKAGE_SECONDARY_TOKEN_KEYS" \
|
|
368
|
+
"$PACKAGE_SECONDARY_OTP"
|
|
369
|
+
fi
|
|
370
|
+
fi
|
|
371
|
+
fi
|
|
372
|
+
|
|
373
|
+
log "Etapa package concluída."
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
finalize() {
|
|
377
|
+
local exit_code=$?
|
|
378
|
+
if [ "$exit_code" -eq 0 ]; then
|
|
379
|
+
github_deploy_status "success"
|
|
380
|
+
else
|
|
381
|
+
github_deploy_status "failure"
|
|
382
|
+
fi
|
|
383
|
+
for npmrc_tmp in "${NPMRC_TMP_FILES[@]:-}"; do
|
|
384
|
+
if [ -n "$npmrc_tmp" ] && [ -f "$npmrc_tmp" ]; then
|
|
385
|
+
rm -f "$npmrc_tmp"
|
|
386
|
+
fi
|
|
387
|
+
done
|
|
388
|
+
rm -rf "$STAGING_DIR"
|
|
389
|
+
}
|
|
390
|
+
trap finalize EXIT
|
|
391
|
+
|
|
392
|
+
log "build_id=$BUILD_ID"
|
|
393
|
+
log "Preparando staging em $STAGING_DIR"
|
|
394
|
+
rsync -a --delete "$SOURCE_DIR"/ "$STAGING_DIR"/
|
|
395
|
+
node "$PROJECT_ROOT/scripts/cache-bust.mjs" --dir "$STAGING_DIR" --version "$BUILD_ID"
|
|
396
|
+
|
|
397
|
+
if [ "$BACKUP_ENABLED" = "1" ] && [ "$DRY_RUN" != "1" ] && [ -d "$DEPLOY_DIR" ]; then
|
|
398
|
+
BACKUP_STAMP="$(date -u +%Y%m%d-%H%M%S)"
|
|
399
|
+
BACKUP_PATH="$BACKUP_DIR/$BACKUP_STAMP"
|
|
400
|
+
log "Criando backup em $BACKUP_PATH"
|
|
401
|
+
as_root mkdir -p "$BACKUP_PATH"
|
|
402
|
+
as_root rsync -a --delete --exclude '.backup/' "$DEPLOY_DIR"/ "$BACKUP_PATH"/
|
|
403
|
+
fi
|
|
404
|
+
|
|
405
|
+
if [ ! -d "$DEPLOY_DIR" ]; then
|
|
406
|
+
log "Criando diretório de deploy $DEPLOY_DIR"
|
|
407
|
+
as_root mkdir -p "$DEPLOY_DIR"
|
|
408
|
+
fi
|
|
409
|
+
|
|
410
|
+
if [ "$DRY_RUN" = "1" ]; then
|
|
411
|
+
log "DRY_RUN=1 ativo. Simulando sync para $DEPLOY_DIR"
|
|
412
|
+
as_root rsync -avhn --delete --exclude '.backup/' "$STAGING_DIR"/ "$DEPLOY_DIR"/
|
|
413
|
+
log "Dry-run finalizado."
|
|
414
|
+
exit 0
|
|
415
|
+
fi
|
|
416
|
+
|
|
417
|
+
github_deploy_start
|
|
418
|
+
run_package_stage
|
|
419
|
+
|
|
420
|
+
log "Sincronizando arquivos para $DEPLOY_DIR"
|
|
421
|
+
as_root rsync -a --delete --exclude '.backup/' "$STAGING_DIR"/ "$DEPLOY_DIR"/
|
|
422
|
+
|
|
423
|
+
log "Validando configuração do nginx"
|
|
424
|
+
as_root nginx -t
|
|
425
|
+
|
|
426
|
+
log "Recarregando serviço $NGINX_SERVICE"
|
|
427
|
+
as_root systemctl reload "$NGINX_SERVICE"
|
|
428
|
+
as_root systemctl is-active --quiet "$NGINX_SERVICE"
|
|
429
|
+
|
|
430
|
+
if [ "$RESTART_PM2" = "1" ] && command -v pm2 >/dev/null 2>&1; then
|
|
431
|
+
if as_root pm2 describe "$PM2_APP_NAME" >/dev/null 2>&1; then
|
|
432
|
+
log "Reiniciando PM2 app $PM2_APP_NAME"
|
|
433
|
+
as_root pm2 restart "$PM2_APP_NAME" --update-env >/dev/null
|
|
434
|
+
else
|
|
435
|
+
log "PM2 app '$PM2_APP_NAME' não encontrada. Restart ignorado."
|
|
436
|
+
fi
|
|
437
|
+
fi
|
|
438
|
+
|
|
439
|
+
if [ -f "$DEPLOY_DIR/index.html" ]; then
|
|
440
|
+
if command -v rg >/dev/null 2>&1; then
|
|
441
|
+
DEPLOYED_REF="$(rg -o '/js/apps/homeApp.js\\?v=[^"]+' "$DEPLOY_DIR/index.html" -m 1 || true)"
|
|
442
|
+
else
|
|
443
|
+
DEPLOYED_REF="$(grep -oE '/js/apps/homeApp\\.js\\?v=[^"]+' "$DEPLOY_DIR/index.html" | head -n 1 || true)"
|
|
444
|
+
fi
|
|
445
|
+
if [ -n "$DEPLOYED_REF" ]; then
|
|
446
|
+
log "Cache-bust aplicado: $DEPLOYED_REF"
|
|
447
|
+
fi
|
|
448
|
+
fi
|
|
449
|
+
|
|
450
|
+
if command -v curl >/dev/null 2>&1; then
|
|
451
|
+
if curl -kfsS "$VERIFY_URL" >/dev/null; then
|
|
452
|
+
log "Health check OK em $VERIFY_URL"
|
|
453
|
+
else
|
|
454
|
+
log "Health check falhou em $VERIFY_URL (deploy concluído, verifique manualmente)."
|
|
455
|
+
fi
|
|
456
|
+
fi
|
|
457
|
+
|
|
458
|
+
log "Deploy concluído com sucesso."
|