@@ -46,8 +46,8 @@ HAS_JAVASCRIPT := $(filter javascript,$(LANGUAGES))
4646# ---------------------------------------------------------------------------
4747# .PHONY declarations
4848# ---------------------------------------------------------------------------
49- .PHONY : help build lint format test security scan docs check install-hooks
50- .PHONY : _lint _format _test _security _scan _docs _check _check-config
49+ .PHONY : help build lint format test security scan docs check install-hooks init
50+ .PHONY : _lint _format _test _security _scan _docs _check _check-config _init
5151
5252# ===========================================================================
5353# Public targets (run on host, delegate to Docker container)
@@ -92,6 +92,9 @@ install-hooks: ## Install pre-commit hooks
9292 @pre-commit install --hook-type commit-msg
9393 @echo " Pre-commit hooks installed successfully. Hooks will run on every commit."
9494
95+ init : # # Scaffold config files for declared languages
96+ $(DOCKER_RUN ) make _init
97+
9598lint : # # Run all linters
9699 $(DOCKER_RUN ) make _lint
97100
@@ -661,6 +664,165 @@ _docs: _check-config
661664 fi ; \
662665 exit $$ overall_exit
663666
667+ # --- _init: scaffold config files for declared languages ---
668+ _init : _check-config
669+ @created=" " ; \
670+ skipped=" " ; \
671+ scaffold () { \
672+ _f=" $$ 1" ; shift ; \
673+ if [ ! -f " $$ _f" ]; then \
674+ printf ' %s\n' " $$ @" > " $$ _f" ; \
675+ created=" $$ {created}\" $$ _f\" ," ; \
676+ else \
677+ skipped=" $$ {skipped}\" $$ _f\" ," ; \
678+ fi ; \
679+ }; \
680+ scaffold .editorconfig \
681+ ' root = true' \
682+ ' ' \
683+ ' [*]' \
684+ ' charset = utf-8' \
685+ ' end_of_line = lf' \
686+ ' insert_final_newline = true' \
687+ ' trim_trailing_whitespace = true' \
688+ ' indent_style = space' \
689+ ' indent_size = 2' \
690+ ' ' \
691+ ' [Makefile]' \
692+ ' indent_style = tab' \
693+ ' ' \
694+ ' [*.py]' \
695+ ' indent_size = 4' \
696+ ' ' \
697+ ' [*.sh]' \
698+ ' indent_size = 2' ; \
699+ if [ -n " $( HAS_PYTHON) " ]; then \
700+ scaffold ruff.toml \
701+ ' line-length = 120' \
702+ ' target-version = "py311"' \
703+ ' ' \
704+ ' [lint]' \
705+ ' select = ["E", "W", "F", "I", "UP", "B", "S", "C4", "SIM"]' \
706+ ' ' \
707+ ' [format]' \
708+ ' quote-style = "double"' \
709+ ' indent-style = "space"' ; \
710+ fi ; \
711+ if [ -n " $( HAS_BASH) " ]; then \
712+ scaffold .shellcheckrc \
713+ ' shell=bash' \
714+ ' enable=all' ; \
715+ fi ; \
716+ if [ -n " $( HAS_TERRAFORM) " ]; then \
717+ scaffold .tflint.hcl \
718+ ' config {' \
719+ ' call_module_type = "local"' \
720+ ' }' \
721+ ' ' \
722+ ' plugin "terraform" {' \
723+ ' enabled = true' \
724+ ' preset = "recommended"' \
725+ ' }' ; \
726+ fi ; \
727+ if [ -n " $( HAS_ANSIBLE) " ]; then \
728+ scaffold .ansible-lint \
729+ ' profile: production' \
730+ ' ' \
731+ ' exclude_paths:' \
732+ ' - .cache/' \
733+ ' - .github/' \
734+ ' - .gitlab/' \
735+ ' ' \
736+ ' skip_list:' \
737+ ' - yaml[truthy]' \
738+ ' ' \
739+ ' warn_list:' \
740+ ' - experimental' ; \
741+ fi ; \
742+ if [ -n " $( HAS_RUBY) " ]; then \
743+ scaffold .rubocop.yml \
744+ ' AllCops:' \
745+ ' TargetRubyVersion: 3.1' \
746+ ' NewCops: enable' \
747+ ' Exclude:' \
748+ ' - "db/schema.rb"' \
749+ ' - "bin/**/*"' \
750+ ' - "vendor/**/*"' \
751+ ' - "node_modules/**/*"' \
752+ ' ' \
753+ ' Style/Documentation:' \
754+ ' Enabled: false' \
755+ ' ' \
756+ ' Metrics/BlockLength:' \
757+ ' Exclude:' \
758+ ' - "spec/**/*"' \
759+ ' ' \
760+ ' Layout/LineLength:' \
761+ ' Max: 120' ; \
762+ scaffold .reek.yml \
763+ ' exclude_paths:' \
764+ ' - vendor' \
765+ ' - db/schema.rb' \
766+ ' - bin' \
767+ ' ' \
768+ ' detectors:' \
769+ ' IrresponsibleModule:' \
770+ ' enabled: false' ; \
771+ scaffold .rspec \
772+ ' --require spec_helper' \
773+ ' --format documentation' \
774+ ' --color' ; \
775+ fi ; \
776+ if [ -n " $( HAS_GO) " ]; then \
777+ scaffold .golangci.yml \
778+ ' version: "2"' \
779+ ' ' \
780+ ' linters:' \
781+ ' enable:' \
782+ ' - errcheck' \
783+ ' - govet' \
784+ ' - staticcheck' \
785+ ' - gosec' \
786+ ' - ineffassign' \
787+ ' - unused' \
788+ ' - gocritic' \
789+ ' - gofumpt' \
790+ ' - misspell' \
791+ ' - revive' \
792+ ' ' \
793+ ' issues:' \
794+ ' exclude-dirs:' \
795+ ' - vendor' \
796+ ' - node_modules' ; \
797+ fi ; \
798+ if [ -n " $( HAS_JAVASCRIPT) " ]; then \
799+ scaffold eslint.config.js \
800+ ' import eslint from "@eslint/js";' \
801+ ' import tseslint from "typescript-eslint";' \
802+ ' ' \
803+ ' export default tseslint.config(' \
804+ ' eslint.configs.recommended,' \
805+ ' tseslint.configs.recommended,' \
806+ ' {' \
807+ ' ignores: ["node_modules/", "dist/", "build/", "coverage/"],' \
808+ ' }' \
809+ ' );' ; \
810+ scaffold .prettierrc \
811+ ' {' \
812+ ' "semi": true,' \
813+ ' "singleQuote": false,' \
814+ ' "trailingComma": "es5",' \
815+ ' "printWidth": 80,' \
816+ ' "tabWidth": 2' \
817+ ' }' ; \
818+ scaffold .prettierignore \
819+ ' node_modules/' \
820+ ' dist/' \
821+ ' build/' \
822+ ' coverage/' ; \
823+ fi ; \
824+ echo " {\" target\" :\" init\" ,\" created\" :[$$ {created%,}],\" skipped\" :[$$ {skipped%,}]}"
825+
664826# --- _check: orchestrate all targets ---
665827_check : _check-config
666828 @overall_exit=0; \
0 commit comments