From siae-devforge
Use when setting up a new datalake ETL repo (datalake-{dominio}-etl) from a reference repo. Trigger: "setup repo etl", "nuovo dominio etl", "crea repo datalake etl", "scaffolding etl", "datalake-{nome}-etl", "setup da riferimento", "clona struttura etl".
How this skill is triggered — by the user, by Claude, or both
Slash command
/siae-devforge:siae-datalake-etl-setupThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
```
╔══════════════════════════════════════════════════════════════════╗
║ ███████╗██╗ █████╗ ███████╗ ██████╗ ███████╗██╗ ██╗ ║
║ ██╔════╝██║██╔══██╗██╔════╝ ██╔══██╗██╔════╝██║ ██║ ║
║ ███████╗██║███████║█████╗ ██║ ██║█████╗ ██║ ██║ ║
║ ╚════██║██║██╔══██║██╔══╝ ██║ ██║██╔══╝ ╚██╗ ██╔╝ ║
║ ███████║██║██║ ██║███████╗ ██████╔╝███████╗ ╚████╔╝ ║
║ ╚══════╝╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝ ╚═══╝ ║
║ 🔨 DevForge · SIAE DATALAKE ETL SETUP ║
║ "Il codice si forgia. Il developer cresce." ║
╚══════════════════════════════════════════════════════════════════╝
Tipo: Flexible | Fase SDLC: 2. Setup & Scaffolding
📊 Dai repo itsiae: I repo datalake-*-etl seguono la stessa struttura: modulo silver-{dominio} con Glue job PySpark, Step Function, EventBridge Scheduler e Terragrunt DRY. Il repo di riferimento canonico è
datalake-sport-etl— pattern senza crawler Bronze dedicato, Step Function che inizia direttamente daRetrieveTablesToUpdate. Standardizzare il setup da questo riferimento riduce il bootstrap da ore a minuti. Fonte: pattern validato sudatalake-sport-etl,datalake-zucchetti-etledatalake-bm-utilizzazioni-etl.
Non tutti i repo datalake-*-etl hanno la stessa struttura. Prima di iniziare, verifica:
| Pattern | Caratteristiche | Repo esempio |
|---|---|---|
| Semplice (consigliato) | Niente crawler Bronze dedicato, SFN inizia da RetrieveTablesToUpdate, variabili STEPFUN_CRON_SCHEDULE/STEPFUN_CRON_STATUS | datalake-sport-etl |
| Con crawler | Step Function separata per crawler Bronze, variabile BRONZE_{DOMINIO}_CRAWLER_NAME, SFN inizia da StartBronzeCrawler | datalake-performing-etl, datalake-pmo-etl |
Il pattern semplice (senza crawler) è il default indipendentemente dal repo di riferimento scelto. Anche se si usa datalake-pmo-etl o datalake-performing-etl come riferimento (es. per struttura Glue o IAM), la Step Function deve comunque iniziare da RetrieveTablesToUpdate — rimuovere gli step crawler dal JSON. Il pattern con crawler si adotta solo se il dominio target richiede esplicitamente un crawler Bronze dedicato.
| Parametro | Descrizione | Esempio |
|---|---|---|
repo-riferimento | Nome del repo ETL di riferimento (default: datalake-sport-etl) | datalake-sport-etl |
repo-target | Path locale del repo ETL da configurare | datalake-zucchetti-etl |
dominio | Nome dominio del repo target (usato per naming risorse) | zucchetti |
glue-jobs | Lista nomi Glue job da creare (kebab-case) | trasferte |
gh-actions-version | Versione siae-gh-actions da usare nei workflow (default: v3.0.0) | v3.0.0 |
Se un parametro obbligatorio manca, chiedi prima di procedere. gh-actions-version ha default v3.0.0 — non chiedere se non fornito, usa il default direttamente.
Datalake ETL Setup Progress:
- [ ] Step 1: Raccolta e validazione parametri
- [ ] Step 2: Analisi struttura repo di riferimento (sport-etl)
- [ ] Step 3: Aggiornamento config.yaml e chart/Chart.yaml
- [ ] Step 4: Aggiornamento live/_envs/ (dev/qa/prod .tmpl)
- [ ] Step 5: Creazione live/shared/terragrunt.hcl
- [ ] Step 6: Creazione live/silver-{dominio}/terragrunt.hcl
- [ ] Step 7: Creazione modules/silver-{dominio}/ (_input, _local, _output, .tf)
- [ ] Step 8: Creazione glue-definitions.yaml
- [ ] Step 9: Creazione orchestration/ (silver-etl.json, new_db_silver_mapping.json)
- [ ] Step 10: Copia glue-jobs/src/libs/ e configs/
- [ ] Step 11: Aggiornamento workflow GitHub Actions alla versione target
- [ ] Step 12: Rimozione scaffolding example
- [ ] Step 13: Aggiornamento README.md
- [ ] Step 14: Primo commit
🟢 SICURO
Verifica che tutti i parametri siano presenti. Proponi datalake-sport-etl come repo di riferimento
se non specificato, spiegando brevemente il motivo (pattern semplice, senza crawler Bronze dedicato).
Dalla coppia repo-riferimento / repo-target, deriva automaticamente:
{DOMINIO} = estratto dal nome repo target: datalake-{dominio}-etl{MODULO} = silver-{dominio} (es. silver-zucchetti){SILVER_CONFIG_KEY} = silver_{dominio} (chiave nei .tmpl){UPDATE_ATTR} = last_silver_{dominio}_update_timeDalla lista glue-jobs, deriva per ogni job:
{nome-job} = nome kebab-case fornito (es. trasferte){nome_tabella_silver} = nome job con trattini sostituiti da underscoreMostra il riepilogo derivazioni e chiedi conferma prima di procedere.
🟢 SICURO
Leggi in parallelo i file chiave del repo di riferimento via gh api:
gh api repos/itsiae/{repo-riferimento}/contents/live/_envs/dev.tmpl | python3 -c "import sys,json,base64; d=json.load(sys.stdin); print(base64.b64decode(d['content']).decode())"
File da leggere:
live/_envs/dev.tmpl
live/_envs/prod.tmpl
live/silver-{dominio-ref}/terragrunt.hcl
modules/silver-{dominio-ref}/_input.tf
modules/silver-{dominio-ref}/glue-jobs.tf
modules/silver-{dominio-ref}/stepfunction-orchestration.tf
modules/silver-{dominio-ref}/orchestration/silver-etl.json
Elenca i file presenti nella directory orchestration:
gh api repos/itsiae/{repo-riferimento}/contents/modules/silver-{dominio-ref}/orchestration | python3 -c "import sys,json; [print(v['name']) for v in json.load(sys.stdin)]"
Identifica il pattern prima di procedere:
silver-etl.json ha "StartAt": "RetrieveTablesToUpdate" → pattern semplice (sport)silver-etl.json ha "StartAt": "StartBronzeCrawler" → pattern con crawlerVedi reference/naming-substitutions.md per la mappa completa.
🟢 SICURO
config.yaml — aggiorna project_name e repository_name:
project_name: datalake-{dominio}-etl
repository_name: datalake-{dominio}-etl
chart/Chart.yaml — aggiorna name e template.repository:
name: datalake-{dominio}-etl
template:
repository: datalake-{dominio}-etl
🟢 SICURO
Crea live/_envs/{env}.tmpl dal riferimento (sport-etl). Il pattern sport usa:
$STEPFUN_CRON_SCHEDULE e $STEPFUN_CRON_STATUS (non $CRON_SCHED)bronze_crawler_name — il dominio non ha crawler Bronze dedicatosilver_{dominio}: (es. silver_zucchetti:)Sostituzioni da applicare:
| Riferimento (sport) | Target (nuovo dominio) |
|---|---|
silver_sport: | silver_{dominio}: |
# Silver Sport vars module | # Silver {dominio} vars module |
Differenza tra ambienti per force_no_window:
dev.tmpl → force_no_window: 1qa.tmpl → force_no_window: 0 (simula il comportamento prod)prod.tmpl → force_no_window: 0Mantieni invariati tutti i placeholder $VARIABILE.
🟢 SICURO
Copia identico dal riferimento — il modulo shared è generico, non contiene il dominio.
Verifica che gli input corrispondano agli output del modulo modules/shared/.
🟢 SICURO
Crea live/silver-{dominio}/terragrunt.hcl dal riferimento sostituendo:
| Riferimento (sport) | Target |
|---|---|
module = "silver-sport" | module = "silver-{dominio}" |
local.stage.silver_sport | local.stage.silver_{dominio} |
Non aggiungere bronze_{dominio}_crawler_name — il pattern sport non lo ha.
Il blocco dependency "shared" rimane identico.
🟢 SICURO
Crea la directory modules/silver-{dominio}/ con i seguenti file:
_input.tf — copia da riferimento sostituendo il nome del modulo nei commenti.
Non aggiungere la variabile bronze_{dominio}_crawler_name — non presente nel pattern sport.
La variabile config deve avere questa struttura (senza bronze_crawler):
variable "config" {
type = object({
enable_glue_metrics = string
enable_glue_observability_metrics = string
enable_spark_ui = string
force_no_window = number
orchestration = map(any)
})
}
_local.tf — identico (usa var.env, var.module generici).
_output.tf — copia identico.
🟢 SICURO
Copia glue-jobs.tf dal riferimento sostituendo:
silver_anagrafiche_glue_etl → silver_{dominio}_glue_etldefault_arguments: aws_cloudwatch_log_group.silver_anagrafiche_glue_etl.name → aws_cloudwatch_log_group.silver_{dominio}_glue_etl.nameNon includere l'argomento --last_iac_upload_job_timestamp — non presente nel pattern sport.
Copia glue-jobs-custom-libraries-upload.tf identico.
🟢 SICURO
Crea modules/silver-{dominio}/glue-definitions.yaml con una entry per ogni job:
jobs:
- job_name: "{nome-job}"
description: "ETL that populates the {nome_underscored} table in the silver layer"
dev_number_of_workers: 2
qa_number_of_workers: 2
prod_number_of_workers: 10
worker_type: "G.1X"
glue_version: "5.0"
execution_class: "FLEX"
enable_gluejob_sparkui: "true"
max_concurrent_runs: 1
timeout_min: 120
file_name: "{nome-job}"
🟢 SICURO
stepfunction-orchestration.tf — copia dal riferimento sostituendo:
scope = "sport" → scope = "{dominio}"crawler_name nel templatefile — pattern sport non lo haIAM policy glue-jobs-permissions: usa le azioni minime necessarie (least privilege):
"Action" : ["glue:StartJobRun", "glue:GetJobRun", "glue:BatchStopJobRun"],
"Resource" : ["arn:aws:glue:${var.region}:${var.account_id}:job/${local.prefix}-*"]
Il Resource è già scoped al prefisso del modulo tramite ${local.prefix}-* — non usare * globale.
Non aggiungere policy crawler-permissions — non presente nel pattern sport.
eventbridge-etl-scheduler.tf — copia identico.
🟢 SICURO
silver-etl.json — copia dal riferimento sostituendo:
"update_attr_name": "last_silver_sport_update_time" → "last_silver_{dominio}_update_time""silver_mapping" nei due step RetrieveTablesToUpdate e UpdateSilverCommitTime:
"silver_mapping": {
"{nome-job}": ["{nome_tabella_silver}"]
}
scope nei DetailType è già gestito dalla variabile Terraform ${scope}Il file si chiama silver-etl.json (invariato). Inizia da "StartAt": "RetrieveTablesToUpdate" — nessuno step crawler.
⚠️
--force_no_windownell'ASL deve essere sempre"0"hardcoded — non passarlo come variabile templatefile. Il valore in.tmplagisce solo suidefault_argumentsdel Glue job al deploy. Iniettarlo nell'ASL farebbe eseguire la Step Function senza finestra temporale ad ogni schedulazione (incluso dev), causando la riscrittura dell'intero datalake.
new_db_silver_mapping.json — crea con il mapping dei job del dominio:
{
"{nome-job}": ["{nome_tabella_silver}"]
}
Nota: il file si chiama new_db_silver_mapping.json (non silver-mapping.json) — nome adottato nel pattern sport.
🟢 SICURO
Copia identici dal riferimento:
glue-jobs/src/libs/__init__.pyglue-jobs/src/libs/custom_classes.pyglue-jobs/configs/dev/app_conf.jsonglue-jobs/configs/dev/log4j2.propertiesglue-jobs/configs/qa/app_conf.jsonglue-jobs/configs/qa/log4j2.propertiesglue-jobs/configs/prod/app_conf.jsonglue-jobs/configs/prod/log4j2.properties⚠️ Il file glue-jobs/src/{nome-job}.py NON va creato qui.
È codice di produzione — va implementato con siae-tdd in una sessione dedicata.
Segnalalo esplicitamente all'utente al termine del setup.
🟢 SICURO
Aggiorna tutti i file in .github/workflows/ che referenziano itsiae/siae-gh-actions.
La versione corrente di riferimento è v3.0.0.
sed -i 's/@v[0-9]\+\.[0-9]\+\.[0-9]\+/@{gh-actions-version}/g' .github/workflows/*.yaml
Dove {gh-actions-version} è il parametro ricevuto in input, default v3.0.0 se non specificato.
Verifica con grep -rn "uses:" .github/workflows/ che tutte le versioni siano allineate.
🔴 CRITICO — Mostra pre-flight card prima di eseguire
| 🔴 CRITICO (Rimozione scaffolding) — 🔨 DevForge · siae-datalake-etl-setup |
|---|
| ⚠️ OPERAZIONE LOCALE IRREVERSIBILE — DELETE SU FILE SYSTEM |
📋 Risorsa: modules/example/, live/example/, chart/ · 🌍 Ambiente: locale (repo-target) |
| ▼ Azioni |
1. rm -rf modules/example/ — rimuove tutti i file dello scaffolding modulo example |
2. rm -rf live/example/ — rimuove tutti i file Terragrunt di esempio |
3. rm -rf chart/ — rimuove la directory chart se non presente nel repo di riferimento sport-etl |
| 💡 Perché: la rimozione è irreversibile senza git; se eseguita su branch sbagliato o prima di un commit, i file sono persi senza possibilità di rollback semplice |
| 🚫 Se NO: lo scaffolding rimane nel repo e potrebbe confondere i deploy Terraform futuri |
⏸️ ATTENDI CONFERMA ESPLICITA — mostra la card e NON eseguire finché l'utente risponde esplicitamente ("sì, procedi" / "no, annulla"). Silenzio ≠ consenso.
Solo dopo "sì, procedi", esegui:
Prima di rimuovere, verifica che non ci siano riferimenti a example nel codice:
grep -rn "example" live/ modules/ --include="*.tf" --include="*.hcl" | grep -v "example/"
Se il grep non restituisce risultati, rimuovi:
modules/example/ (tutti i file)live/example/ (tutti i file)chart/ — da rimuovere se non presente nel repo di riferimento sport-etl🟢 SICURO
Aggiorna README.md con le informazioni specifiche del dominio.
Vedi reference/readme-template.md per il template completo.
🔴 CRITICO — Mostra pre-flight card prima di eseguire
| 🔴 CRITICO (GitHub Env Sync) — 🔨 DevForge · siae-datalake-etl-setup |
|---|
| ⚠️ OPERAZIONE REMOTA — WRITE/UPDATE SU GITHUB ENVIRONMENTS (VARIABILI AWS CI/CD) |
📋 Risorsa: itsiae/datalake-{dominio}-etl · 🌍 Ambiente: collaudo, certificazione, produzione |
| ▼ Azioni |
1. Copia/aggiorna le variabili GitHub Actions da datalake-sport-etl verso il repo target |
2. Variabili interessate: AWS_ENV, AWS_ORG_ACCOUNT, AWS_REGION, AWS_ROLE, AWS_TARGET_ACCOUNT_ID, BRONZE_DATALAKE_BUCKET_ID, SILVER_DATALAKE_BUCKET_ID, DYNAMO_BRONZE_TABLE_UPDATE_ID, EVENTBRIDGE_DATALAKE_BUS_ID, EVENTBRIDGE_DATAPLATFORM_ERRORS_ID, GLUE_PACKAGES_BUCKET_ID, GLUE_SPARKUI_BUCKET_ID, LOGS_RETENTION_DAYS, OPEN_LINEAGE_DOMAIN_ID, SILVER_UPDATES_MANAGER_LAMBDA_ARN, STEPFUN_CRON_SCHEDULE, STEPFUN_CRON_STATUS, VPC_STAGE |
| 💡 Perché: le variabili GitHub environments controllano i parametri AWS (account, region, ruoli IAM, bucket) usati dalle pipeline CI/CD; una modifica errata può rompere i deploy su tutti gli ambienti |
| 🚫 Se NO: le variabili CI/CD rimangono quelle di default del repo template e i deploy falliranno |
⏸️ ATTENDI CONFERMA ESPLICITA — mostra la card e NON eseguire finché l'utente risponde esplicitamente ("sì, procedi" / "no, annulla"). Silenzio ≠ consenso.
Solo dopo "sì, procedi", esegui tramite sub-skill:
REQUIRED SUB-SKILL: siae-github-env-sync
Dopo il commit iniziale, sincronizza le variabili GitHub Actions dalla repo di riferimento
(datalake-sport-etl) verso il repo target per tutti gli ambienti (collaudo, certificazione, produzione).
Le variabili del pattern sport includono (senza BRONZE_*_CRAWLER_NAME):
AWS_ENV, AWS_ORG_ACCOUNT, AWS_REGION, AWS_ROLE, AWS_TARGET_ACCOUNT_IDBRONZE_DATALAKE_BUCKET_ID, SILVER_DATALAKE_BUCKET_IDDYNAMO_BRONZE_TABLE_UPDATE_IDEVENTBRIDGE_DATALAKE_BUS_ID, EVENTBRIDGE_DATAPLATFORM_ERRORS_IDGLUE_PACKAGES_BUCKET_ID, GLUE_SPARKUI_BUCKET_IDLOGS_RETENTION_DAYSOPEN_LINEAGE_DOMAIN_IDSILVER_UPDATES_MANAGER_LAMBDA_ARNSTEPFUN_CRON_SCHEDULE, STEPFUN_CRON_STATUSVPC_STAGENon sono presenti CRON_SCHED, CRON_SCHED_STATUS, BRONZE_*_CRAWLER_NAME — questi appartengono al pattern con crawler (pmo/performing).
🔴 ALTO — pre-flight card obbligatoria
REQUIRED SUB-SKILL: siae-git-workflow
Messaggio commit convenzionale:
chore(setup): initial repo setup for {dominio}-etl domain
Se il repo di riferimento non esiste su GitHub o localmente:
Se il dominio target richiede un crawler Bronze dedicato:
datalake-performing-etl come riferimento invece di sportbronze_{dominio}_crawler_name negli input, nelle variabili e nel templatefileCRON_SCHED/CRON_SCHED_STATUS e BRONZE_{DOMINIO}_CRAWLER_NAMESe l'utente chiede di creare anche il file .py:
siae-tdd| Operazione | Livello | Card |
|---|---|---|
| Lettura repo di riferimento via gh api | 🟢 Sicuro | No |
| Scrittura file Terraform/Terragrunt | 🟢 Sicuro | No |
| Scrittura _envs/*.tmpl | 🟢 Sicuro | No |
| Aggiornamento workflow versioni | 🟢 Sicuro | No |
| Rimozione scaffolding example | 🔴 Critico | Sì (gate inline Step 14) |
| Scrittura README.md | 🟢 Sicuro | No |
| GitHub Env Sync | 🔴 Critico | Sì (gate inline Step 16 + siae-github-env-sync) |
| git commit + push | 🔴 Alto | Sì (siae-git-workflow) |
.py del Glue job — è codice di produzione, richiede siae-tdd$VARIABILE nei .tmpl con valori reali — sono placeholder CI/CDglue:* vietato — usa sempre ["glue:StartJobRun", "glue:GetJobRun", "glue:BatchStopJobRun"] con Resource scoped su ${local.prefix}-*new_db_silver_mapping.json è il nome corretto del file mapping nel pattern sport (non silver-mapping.json)STEPFUN_CRON_SCHEDULE/STEPFUN_CRON_STATUS sono le variabili corrette nel pattern sportforce_no_window: 0 in prod e 1 in dev/qarm -rf), env sync GitHub (variabili AWS CI/CD), git push; silenzio ≠ consenso--force_no_window: "0" nell'ASL JSON sempre hardcoded — non iniettare il valore da templatefile variable; il campo .tmpl è usato esclusivamente dai default_arguments Glue al deploy, non dalla Step Function a runtimeProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub itsiae/siae-dev-forge --plugin siae-devforge