{"id":77048,"date":"2024-09-17T23:44:24","date_gmt":"2024-09-17T20:14:24","guid":{"rendered":"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/"},"modified":"2024-09-17T23:44:24","modified_gmt":"2024-09-17T20:14:24","slug":"adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo","status":"publish","type":"post","link":"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/","title":{"rendered":"\u0627\u0641\u0632\u0648\u062f\u0646 lint-staged \u0628\u0647 \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u0647\u0627\u06cc NestJS \u0648 Angular\u060c \u0627\u0645\u06a9\u0627\u0646 \u0646\u0633\u062e\u0647\u200c\u0633\u0627\u0632\u06cc \u0645\u0639\u0646\u0627\u06cc\u06cc frontend"},"content":{"rendered":"<p>Summarize this content to 400 words in Persian Lang \u0627\u0632 \u0632\u0645\u0627\u0646\u06cc \u06a9\u0647 \u0646\u0633\u062e\u0647 \u0627\u0632 \u0637\u0631\u06cc\u0642 nx-semantic-release \u0627\u0641\u0632\u0648\u0646\u0647 \u0628\u0627 \u062a\u062c\u0632\u06cc\u0647 \u0648 \u062a\u062d\u0644\u06cc\u0644 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0645\u0631\u0628\u0648\u0637 \u0628\u0647 \u0622\u0646 \u0635\u0648\u0631\u062a \u0645\u06cc \u06af\u06cc\u0631\u062f Typescript \u0648\u0627\u0631\u062f\u0627\u062a\u060c \u0628\u0627\u06cc\u062f \u0627\u06cc\u0646 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0631\u0627 \u0628\u0647 \u062d\u062f\u0627\u0642\u0644 \u0628\u0631\u0633\u0627\u0646\u06cc\u0645\u060c \u0628\u0631\u0627\u06cc \u0627\u0646\u062c\u0627\u0645 \u0627\u06cc\u0646 \u06a9\u0627\u0631\u060c \u0628\u0647 \u067e\u0631\u0648\u0698\u0647 https:\/\/www.npmjs.com\/package\/lint-staged \u0645\u062a\u0635\u0644 \u0645\u06cc \u0634\u0648\u06cc\u0645 \u0648 \u0633\u062e\u062a \u06af\u06cc\u0631\u06cc \u0631\u0627 \u0628\u0647 \u0622\u0646 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645. Typescript \u06a9\u062f<\/p>\n<p>  1. \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 lint-staged \u0628\u0631\u0627\u06cc \u0642\u0627\u0644\u0628 \u0628\u0646\u062f\u06cc \u06a9\u062f \u0647\u0646\u06af\u0627\u0645 \u0627\u0646\u062c\u0627\u0645<\/p>\n<p>\u0627\u06cc\u0646 \u0627\u0628\u0632\u0627\u0631 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0647\u0627\u06cc \u062e\u0627\u0635\u06cc \u0631\u0627 \u0628\u0627 \u0647\u0631 commit \u0627\u062c\u0631\u0627 \u0645\u06cc \u06a9\u0646\u062f\u060c \u0628\u0647 \u0637\u0648\u0631\u06cc \u06a9\u0647 \u0642\u0627\u0644\u0628 \u0628\u0646\u062f\u06cc \u06a9\u062f \u062f\u0631 git \u0645\u062e\u0632\u0646 \u0647\u0645\u06cc\u0634\u0647 \u06cc\u06a9\u0633\u0627\u0646 \u0627\u0633\u062a\u060c \u0645\u0647\u0645 \u0646\u06cc\u0633\u062a \u06a9\u0647 \u062a\u0648\u0633\u0639\u0647 \u062f\u0647\u0646\u062f\u0647 \u0686\u06af\u0648\u0646\u0647 \u0645\u062d\u06cc\u0637 \u062a\u0648\u0633\u0639\u0647 \u0645\u062d\u0644\u06cc \u062e\u0648\u062f \u0631\u0627 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u06a9\u0631\u062f\u0647 \u0627\u0633\u062a.<\/p>\n<p>\u062f\u0633\u062a\u0648\u0631\u0627\u062a<\/p>\n<p>npx mrm@2 lint-staged<\/p>\n<p>\u062e\u0631\u0648\u062c\u06cc \u0647\u0627\u06cc \u06a9\u0646\u0633\u0648\u0644<\/p>\n<p>$ npx mrm@2 lint-staged<br \/>\nRunning lint-staged&#8230;<br \/>\nUpdate package.json<br \/>\nInstalling husky&#8230;<\/p>\n<p>added 1 package, removed 1 package, and audited 2765 packages in 18s<\/p>\n<p>331 packages are looking for funding<br \/>\n  run `npm fund` for details<\/p>\n<p>49 vulnerabilities (31 moderate, 18 high)<\/p>\n<p>To address issues that do not require attention, run:<br \/>\n  npm audit fix<\/p>\n<p>To address all issues possible (including breaking changes), run:<br \/>\n  npm audit fix &#8211;force<\/p>\n<p>Some issues need review, and may require choosing<br \/>\na different dependency.<\/p>\n<p>Run `npm audit` for details.<br \/>\nhusky &#8211; Git hooks installed<br \/>\nhusky &#8211; created .husky\/pre-commit<\/p>\n<p>  2. \u0645\u0627 \u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0622\u0645\u0627\u062f\u0647 \u0648 \u0628\u062e\u0634 lint-staged \u062f\u0631 root package.json \u0647\u0633\u062a\u06cc\u0645.<\/p>\n<p>\u0631\u0627 prepare \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u067e\u0633 \u0627\u0632 \u0646\u0635\u0628 \u0628\u0647 \u0637\u0648\u0631 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0627\u06cc\u062c\u0627\u062f \u0645\u06cc \u0634\u0648\u062f lint-staged\u060c \u0645\u0646 \u0622\u0646 \u0631\u0627 \u062d\u0630\u0641 \u0646\u06a9\u0631\u062f\u0645\u060c \u0641\u0642\u0637 \u0631\u0648\u0634 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0631\u0627 \u06a9\u0645\u06cc \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0627\u062f\u0645\u060c \u0622\u0646 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0631\u062f\u0645 npx.<\/p>\n<p>\u062f\u0631 \u067e\u0631\u0648\u0698\u0647 \u0647\u0627\u06cc \u06a9\u0648\u0686\u06a9\u060c pre-commit \u0642\u0644\u0627\u0628 \u0628\u0627 lint-staged \u0628\u0647 \u0633\u0631\u0639\u062a \u06a9\u0627\u0631 \u0645\u06cc\u200c\u06a9\u0646\u062f\u060c \u0627\u0645\u0627 \u0627\u06af\u0631 \u067e\u0631\u0648\u0698\u0647 \u0628\u0632\u0631\u06af \u0628\u0627\u0634\u062f\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u062f \u0637\u0648\u0644\u0627\u0646\u06cc\u200c\u062a\u0631 \u06a9\u0627\u0631 \u06a9\u0646\u062f\u060c \u062f\u0631 \u0627\u06cc\u0646 \u0635\u0648\u0631\u062a \u0628\u0631\u0627\u06cc \u0647\u0645\u0647 \u062a\u0648\u0633\u0639\u0647\u200c\u062f\u0647\u0646\u062f\u06af\u0627\u0646 \u0622\u0633\u0627\u0646\u200c\u062a\u0631 \u0627\u0633\u062a \u06a9\u0647 \u0631\u0648\u06cc \u06cc\u06a9 \u0633\u0628\u06a9 \u0642\u0627\u0644\u0628\u200c\u0628\u0646\u062f\u06cc \u0645\u0634\u062a\u0631\u06a9 \u0628\u0647 \u062a\u0648\u0627\u0641\u0642 \u0628\u0631\u0633\u0646\u062f \u062a\u0627 \u062a\u0639\u062f\u0627\u062f \u0641\u0627\u06cc\u0644\u200c\u0647\u0627\u06cc\u06cc \u0631\u0627 \u06a9\u0647 \u0644\u06cc\u0646\u062a\u0631\u0647\u0627 \u0628\u0627\u06cc\u062f \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u0646\u062f\u060c \u06a9\u0627\u0647\u0634 \u062f\u0647\u0646\u062f.<\/p>\n<p>\u062f\u0631 pre-commit \u0642\u0644\u0627\u0628\u060c \u0646\u06cc\u0627\u0632\u06cc \u0628\u0647 \u062a\u062c\u0648\u06cc\u0632 \u0639\u0645\u0644\u06cc\u0627\u062a \u0633\u0646\u06af\u06cc\u0646 \u0645\u062e\u062a\u0644\u0641 \u0646\u06cc\u0633\u062a\u060c \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644: \u062a\u0648\u0644\u06cc\u062f \u0645\u0634\u062a\u0631\u06cc frontend\u060c \u0686\u0646\u06cc\u0646 \u0639\u0645\u0644\u06cc\u0627\u062a\u06cc \u0628\u0647\u062a\u0631 \u0627\u0633\u062a \u062f\u0631 CI\/CD \u06cc\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u0628\u0627 \u062f\u0633\u062a \u062f\u0631 \u0635\u0648\u0631\u062a \u0646\u06cc\u0627\u0632\u060c \u0648 \u0646\u0647 \u0628\u0631\u0627\u06cc \u0647\u0631 commit.<\/p>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0628\u062e\u0634\u06cc \u0627\u0632 package.json \u0641\u0627\u06cc\u0644<\/p>\n<p>{<br \/>\n  &#8220;scripts&#8221;: {<br \/>\n    \/\/ &#8230;<br \/>\n    &#8220;prepare&#8221;: &#8220;npx -y husky install&#8221;<br \/>\n    \/\/ &#8230;<br \/>\n  },<br \/>\n  \/\/ &#8230;<br \/>\n  &#8220;lint-staged&#8221;: {<br \/>\n    &#8220;*.{js,ts}&#8221;: &#8220;eslint &#8211;fix&#8221;,<br \/>\n    &#8220;*.{js,ts,css,scss,md}&#8221;: &#8220;prettier &#8211;ignore-unknown &#8211;write&#8221;,<br \/>\n    &#8220;*.js&#8221;: &#8220;eslint &#8211;cache &#8211;fix&#8221;<br \/>\n  }<br \/>\n  \/\/ &#8230;<br \/>\n}<\/p>\n<p>  3. \u0642\u0627\u0644\u0628 \u0628\u0646\u062f\u06cc \u0645\u0631\u062d\u0644\u0647 \u067e\u0631\u0632 \u0631\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u062f\u0633\u062a\u06cc \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u062f<\/p>\n<p>\u0628\u0647 \u0645\u0646\u0638\u0648\u0631 \u0628\u0631\u0631\u0633\u06cc \u062f\u0633\u062a\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f lint-staged\u060c \u0628\u0627\u06cc\u062f \u0647\u0645\u0647 \u0641\u0627\u06cc\u0644 \u0647\u0627 \u0631\u0627 \u0628\u0647 \u0622\u0646 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f stage \u0648 \u0622\u0646 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f npx.<\/p>\n<p>\u062f\u0633\u062a\u0648\u0631\u0627\u062a<\/p>\n<p>git add .<br \/>\nnpx lint-staged<\/p>\n<p>\u062e\u0631\u0648\u062c\u06cc \u0647\u0627\u06cc \u06a9\u0646\u0633\u0648\u0644<\/p>\n<p> npx lint-staged<br \/>\n\u2714 Preparing lint-staged&#8230;<br \/>\n\u2714 Running tasks for staged files&#8230;<br \/>\n\u2714 Applying modifications from tasks&#8230;<br \/>\n\u2714 Cleaning up temporary files&#8230;<\/p>\n<p>  4. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc package.json \u0648 NX \u062f\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 \u0647\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc<\/p>\n<p>\u0627\u0632 \u0622\u0646\u062c\u0627\u06cc\u06cc \u06a9\u0647 \u062f\u0631 \u067e\u0633\u062a \u0642\u0628\u0644\u06cc \u0627\u0646\u062a\u0634\u0627\u0631 \u062f\u0631 \u0631\u0627 \u063a\u06cc\u0631\u0641\u0639\u0627\u0644 \u06a9\u0631\u062f\u06cc\u0645 npm\u060c \u0645\u0627 \u0646\u0633\u062e\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u0627 \u062f\u0631 \u06a9\u062f \u0645\u0646\u0628\u0639 \u062a\u063a\u06cc\u06cc\u0631 \u0646\u062f\u0627\u062f\u06cc\u0645 \u062a\u0627 \u0646\u0633\u062e\u0647 \u0645\u0648\u062c\u0648\u062f \u062f\u0631 \u06a9\u062f \u0645\u0646\u0628\u0639 \u062a\u063a\u06cc\u06cc\u0631 \u06a9\u0646\u062f \u0648 \u0627\u06cc\u0646 \u0627\u0646\u062a\u0634\u0627\u0631 \u062f\u0631 npm \u0634\u0631\u0648\u0639 \u0646\u0634\u062f\u060c \u0628\u0627\u06cc\u062f \u06af\u0632\u06cc\u0646\u0647 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f &#8220;private&#8221;: true.<\/p>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc apps\/server\/package.json \u0641\u0627\u06cc\u0644<\/p>\n<p>{<br \/>\n  &#8220;name&#8221;: &#8220;server&#8221;,<br \/>\n  &#8220;version&#8221;: &#8220;0.0.3&#8221;,<br \/>\n  &#8220;private&#8221;: true,<br \/>\n  &#8220;scripts&#8221;: {},<br \/>\n  &#8220;dependencies&#8221;: {<br \/>\n    &#8220;pm2&#8221;: &#8220;&gt;=5.3.0&#8221;,<br \/>\n    &#8220;dotenv&#8221;: &#8220;&gt;=16.3.1&#8221;<br \/>\n  },<br \/>\n  &#8220;devScripts&#8221;: [&#8220;manual:prepare&#8221;, &#8220;serve:dev:server&#8221;],<br \/>\n  &#8220;prodScripts&#8221;: [&#8220;manual:prepare&#8221;, &#8220;start:prod:server&#8221;],<br \/>\n  &#8220;testsScripts&#8221;: [&#8220;test:server&#8221;]\n}<\/p>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0628\u062e\u0634\u06cc \u0627\u0632 apps\/server\/package.json \u0641\u0627\u06cc\u0644<\/p>\n<p>{<br \/>\n  &#8220;name&#8221;: &#8220;server&#8221;,<br \/>\n  \/\/ &#8230;<br \/>\n  &#8220;targets&#8221;: {<br \/>\n    \/\/ &#8230;<br \/>\n    &#8220;semantic-release&#8221;: {<br \/>\n      &#8220;executor&#8221;: &#8220;@theunderscorer\/nx-semantic-release:semantic-release&#8221;,<br \/>\n      &#8220;options&#8221;: {<br \/>\n        &#8220;github&#8221;: true,<br \/>\n        &#8220;changelog&#8221;: true,<br \/>\n        &#8220;npm&#8221;: true,<br \/>\n        &#8220;tagFormat&#8221;: &#8220;server-v${VERSION}&#8221;<br \/>\n      }<br \/>\n    }<br \/>\n  }<br \/>\n}<\/p>\n<p>  5. \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 package.json \u062f\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 frontend \u0648 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u062f\u0633\u062a\u0648\u0631 semantic-release \u0628\u0647 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc NX \u0622\u0646<\/p>\n<p>\u0642\u0628\u0644\u0627 \u062f\u0631 \u067e\u0633\u062a \u0647\u0627\u060c \u0645\u0627 \u0631\u0627 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u06a9\u0631\u062f\u06cc\u0645 Nginx \u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u0646\u0633\u062e\u0647 \u067e\u0634\u062a\u06cc\u0628\u0627\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u062a\u063a\u06cc\u06cc\u0631 \u06a9\u0631\u062f\u060c \u0627\u0631\u062a\u0642\u0627 \u062f\u0647\u06cc\u062f.<\/p>\n<p>\u0628\u0647 \u0645\u0646\u0638\u0648\u0631 \u0628\u0631\u0627\u06cc Nginx \u062a\u0635\u0648\u06cc\u0631 \u0628\u0627 \u06cc\u06a9 \u062c\u0644\u0648\u06cc \u062a\u0639\u0628\u06cc\u0647 \u0634\u062f\u0647 \u06a9\u0647 \u0641\u0642\u0637 \u0632\u0645\u0627\u0646\u06cc \u06a9\u0647 \u0642\u0633\u0645\u062a \u0638\u0627\u0647\u0631\u06cc \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc \u06a9\u0646\u062f \u0645\u0648\u0646\u062a\u0627\u0698 \u0645\u06cc \u0634\u0648\u062f\u060c \u0628\u0627\u06cc\u062f \u0642\u0633\u0645\u062a \u062c\u0644\u0648\u06cc\u06cc \u0631\u0627 \u0646\u0633\u062e\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u0645 \u0648 \u0627\u0632 \u0646\u0633\u062e\u0647 \u0622\u0646 \u062f\u0631 \u0645\u0646\u0637\u0642 \u0647\u0627\u06cc \u0628\u0639\u062f\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u0645. Docker \u062a\u0635\u0627\u0648\u06cc\u0631 \u0648 Kubernetes \u0642\u0627\u0644\u0628 \u0647\u0627<\/p>\n<p>\u0646\u0633\u062e\u0647\u200c\u0633\u0627\u0632\u06cc \u0645\u0639\u0646\u0627\u06cc\u06cc \u0646\u06cc\u0627\u0632 \u0628\u0647 \u0627\u0644\u0641 \u062f\u0627\u0631\u062f package.json \u0628\u0631\u0627\u06cc \u06a9\u0627\u0631 \u0628\u0627 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 \u06cc\u0627 \u0628\u0631\u0646\u0627\u0645\u0647\u060c \u0628\u0646\u0627\u0628\u0631\u0627\u06cc\u0646 \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 frontend \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0647 \u0648 \u0645\u0634\u062e\u0635 \u0645\u06cc \u06a9\u0646\u06cc\u0645 &#8220;private&#8221;: true.<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f apps\/client\/package.json \u0641\u0627\u06cc\u0644<\/p>\n<p>{<br \/>\n  &#8220;name&#8221;: &#8220;client&#8221;,<br \/>\n  &#8220;version&#8221;: &#8220;0.0.1&#8221;,<br \/>\n  &#8220;private&#8221;: true<br \/>\n}<\/p>\n<p>\u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0647\u062f\u0641 \u062c\u062f\u06cc\u062f \u0628\u0647 apps\/client\/project.json \u0641\u0627\u06cc\u0644<\/p>\n<p>{<br \/>\n  &#8220;name&#8221;: &#8220;client&#8221;,<br \/>\n  \/\/ &#8230;<br \/>\n  &#8220;targets&#8221;: {<br \/>\n    \/\/ &#8230;<br \/>\n    &#8220;semantic-release&#8221;: {<br \/>\n      &#8220;executor&#8221;: &#8220;@theunderscorer\/nx-semantic-release:semantic-release&#8221;,<br \/>\n      &#8220;options&#8221;: {<br \/>\n        &#8220;github&#8221;: true,<br \/>\n        &#8220;changelog&#8221;: true,<br \/>\n        &#8220;npm&#8221;: true,<br \/>\n        &#8220;tagFormat&#8221;: &#8220;client-v${VERSION}&#8221;<br \/>\n      }<br \/>\n    }<br \/>\n  }<br \/>\n}<\/p>\n<p>  6. \u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0645\u062a\u063a\u06cc\u0631 \u0645\u062d\u06cc\u0637 \u067e\u0648\u06cc\u0627 \u062c\u062f\u06cc\u062f<\/p>\n<p>\u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0645\u062a\u063a\u06cc\u0631 \u062c\u062f\u06cc\u062f \u0628\u0627 \u0646\u0633\u062e\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 frontend \u0628\u0647 \u0641\u0627\u06cc\u0644 .kubernetes\/set-env.sh \u0648 .docker\/set-env.sh<\/p>\n<p>export CLIENT_VERSION=$(cd .\/apps\/client &amp;&amp; npm pkg get version &#8211;workspaces=false | tr -d \\&#8221;)<\/p>\n<p>  7. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0641\u0627\u06cc\u0644<\/p>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0641\u0627\u06cc\u0644 .kubernetes\/templates\/client\/3.deployment.yaml<\/p>\n<p>apiVersion: apps\/v1<br \/>\nkind: Deployment<br \/>\nmetadata:<br \/>\n  namespace: &#8216;%NAMESPACE%&#8217;<br \/>\n  name: %NAMESPACE%-client<br \/>\nspec:<br \/>\n  replicas: 1<br \/>\n  selector:<br \/>\n    matchLabels:<br \/>\n      pod: %NAMESPACE%-client-container<br \/>\n  template:<br \/>\n    metadata:<br \/>\n      namespace: &#8216;%NAMESPACE%&#8217;<br \/>\n      labels:<br \/>\n        app: %NAMESPACE%-client<br \/>\n        pod: %NAMESPACE%-client-container<br \/>\n    spec:<br \/>\n      containers:<br \/>\n        &#8211; name: %NAMESPACE%-client<br \/>\n          image: ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-nginx:%CLIENT_VERSION%<br \/>\n          imagePullPolicy: IfNotPresent<br \/>\n          ports:<br \/>\n            &#8211; containerPort: %NGINX_PORT%<br \/>\n          envFrom:<br \/>\n            &#8211; configMapRef:<br \/>\n                name: %NAMESPACE%-config<br \/>\n            &#8211; configMapRef:<br \/>\n                name: %NAMESPACE%-client-config<br \/>\n          resources:<br \/>\n            requests:<br \/>\n              memory: 128Mi<br \/>\n              cpu: 100m<br \/>\n            limits:<br \/>\n              memory: 512Mi<br \/>\n              cpu: 300m<br \/>\n      imagePullSecrets:<br \/>\n        &#8211; name: docker-regcred<\/p>\n<p>  8. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0627\u0633\u062a\u0642\u0631\u0627\u0631 CI\/CD \u0628\u0631\u0627\u06cc Kubernetes \u0648 Docker Compose<\/p>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0622\u067e\u062f\u06cc\u062a \u0628\u062e\u0634\u06cc \u0627\u0632 \u0641\u0627\u06cc\u0644 .github\/workflows\/kubernetes.yml \u0648 .github\/workflows\/docker-compose.workflows.yml<\/p>\n<p>jobs:<br \/>\n  # &#8230;<br \/>\n  check-nginx-image:<br \/>\n    runs-on: ubuntu-latest<br \/>\n    needs: [release]\n    continue-on-error: true<br \/>\n    steps:<br \/>\n      &#8211; name: Checkout repository<br \/>\n        if: ${{ !contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) &amp;&amp; !contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) }}<br \/>\n        uses: actions\/checkout@v4<br \/>\n      &#8211; name: Set ENV vars<br \/>\n        if: ${{ !contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) &amp;&amp; !contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) }}<br \/>\n        id: version<br \/>\n        run: |<br \/>\n          echo &#8220;client_version=&#8221;$(cd .\/apps\/client &amp;&amp; npm pkg get version &#8211;workspaces=false | tr -d \\&#8221;) &gt;&gt; &#8220;$GITHUB_OUTPUT&#8221;<br \/>\n      &#8211; name: Check exists docker image<br \/>\n        if: ${{ !contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) &amp;&amp; !contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) }}<br \/>\n        id: check-exists<br \/>\n        run: |<br \/>\n          export TOKEN=$(curl -u ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} https:\/\/${{ env.REGISTRY }}\/token\\?scope\\=&#8221;repository:${{ env.NGINX_IMAGE_NAME}}:pull&#8221; | jq -r .token)<br \/>\n          curl &#8211;head &#8211;fail -H &#8220;Authorization: Bearer $TOKEN&#8221; https:\/\/${{ env.REGISTRY }}\/v2\/${{ env.NGINX_IMAGE_NAME}}\/manifests\/${{ steps.version.outputs.client_version }}<br \/>\n      &#8211; name: Store result of check exists docker image<br \/>\n        id: store-check-exists<br \/>\n        if: ${{ !contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) &amp;&amp; !contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) &amp;&amp; !contains(needs.check-exists.outputs.result, &#8216;HTTP\/2 404&#8217;) }}<br \/>\n        run: |<br \/>\n          echo &#8220;conclusion=success&#8221; &gt;&gt; &#8220;$GITHUB_OUTPUT&#8221;<br \/>\n    outputs:<br \/>\n      result: ${{ steps.store-check-exists.outputs.conclusion }}<br \/>\n  # &#8230;<br \/>\n  build-and-push-nginx-image:<br \/>\n    runs-on: ubuntu-latest<br \/>\n    needs: [build-and-push-builder-image, check-nginx-image]\n    permissions:<br \/>\n      contents: read<br \/>\n      packages: write<br \/>\n      attestations: write<br \/>\n      id-token: write<br \/>\n    steps:<br \/>\n      &#8211; name: Checkout repository<br \/>\n        if: ${{ needs.check-nginx-image.outputs.result != &#8216;success&#8217; || contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) || contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) }}<br \/>\n        uses: actions\/checkout@v4<br \/>\n      &#8211; name: Set ENV vars<br \/>\n        if: ${{ needs.check-nginx-image.outputs.result != &#8216;success&#8217; || contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) || contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) }}<br \/>\n        id: version<br \/>\n        run: |<br \/>\n          echo &#8220;root_version=&#8221;$(npm pkg get version &#8211;workspaces=false | tr -d \\&#8221;) &gt;&gt; &#8220;$GITHUB_OUTPUT&#8221;<br \/>\n          echo &#8220;client_version=&#8221;$(cd .\/apps\/client &amp;&amp; npm pkg get version &#8211;workspaces=false | tr -d \\&#8221;) &gt;&gt; &#8220;$GITHUB_OUTPUT&#8221;<br \/>\n      &#8211; name: Log in to the Container registry<br \/>\n        if: ${{ needs.check-nginx-image.outputs.result != &#8216;success&#8217; || contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) || contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) }}<br \/>\n        uses: docker\/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1<br \/>\n        with:<br \/>\n          registry: ${{ env.REGISTRY }}<br \/>\n          username: ${{ github.actor }}<br \/>\n          password: ${{ secrets.GITHUB_TOKEN }}<br \/>\n      &#8211; name: Generate and build production code<br \/>\n        if: ${{ needs.check-nginx-image.outputs.result != &#8216;success&#8217; || contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) || contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) }}<br \/>\n        run: |<br \/>\n          mkdir -p dist<br \/>\n          docker run -v .\/dist:\/usr\/src\/app\/dist -v .\/apps:\/usr\/src\/app\/apps -v .\/libs:\/usr\/src\/app\/libs ${{ env.REGISTRY}}\/${{ env.BUILDER_IMAGE_NAME}}:${{ steps.version.outputs.root_version }}<br \/>\n      &#8211; name: Build and push Docker image<br \/>\n        if: ${{ needs.check-nginx-image.outputs.result != &#8216;success&#8217; || contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) || contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) }}<br \/>\n        id: push<br \/>\n        uses: docker\/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4<br \/>\n        with:<br \/>\n          context: .<br \/>\n          push: true<br \/>\n          file: .\/.docker\/nginx.Dockerfile<br \/>\n          tags: ${{ env.REGISTRY}}\/${{ env.NGINX_IMAGE_NAME}}:${{ steps.version.outputs.client_version }},${{ env.REGISTRY}}\/${{ env.NGINX_IMAGE_NAME}}:latest<br \/>\n          cache-from: type=registry,ref=${{ env.REGISTRY}}\/${{ env.NGINX_IMAGE_NAME}}:${{ steps.version.outputs.client_version }}<br \/>\n          cache-to: type=inline<br \/>\n      &#8211; name: Generate artifact attestation<br \/>\n        continue-on-error: true<br \/>\n        if: ${{ needs.check-nginx-image.outputs.result != &#8216;success&#8217; || contains(github.event.head_commit.message, &#8216;[skip cache]&#8217;) || contains(github.event.head_commit.message, &#8216;[skip nginx cache]&#8217;) }}<br \/>\n        uses: actions\/attest-build-provenance@v1<br \/>\n        with:<br \/>\n          subject-name: ${{ env.REGISTRY }}\/${{ env.NGINX_IMAGE_NAME}}<br \/>\n          subject-digest: ${{ steps.push.outputs.digest }}<br \/>\n          push-to-registry: true<\/p>\n<p>  9. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u062c\u0645\u0639 \u0622\u0648\u0631\u06cc \u06a9\u0646\u0646\u062f\u0647 \u062a\u0635\u0648\u06cc\u0631 \u0645\u062d\u0644\u06cc Docker<\/p>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0641\u0627\u06cc\u0644 .docker\/build-images.sh<\/p>\n<p>#!\/bin\/bash<br \/>\nset -e<\/p>\n<p># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<br \/>\nexport IMG=${REGISTRY}\/${BUILDER_IMAGE_NAME}:${ROOT_VERSION} &amp;&amp; [ -n &#8220;$(docker images -q $IMG)&#8221; ] || docker build &#8211;network host -t &#8220;${REGISTRY}\/${BUILDER_IMAGE_NAME}:${ROOT_VERSION}&#8221; -t &#8220;${REGISTRY}\/${BUILDER_IMAGE_NAME}:latest&#8221; -f .\/.docker\/builder.Dockerfile . &#8211;progress=plain<\/p>\n<p># We build all applications<br \/>\ndocker run &#8211;network host -v .\/dist:\/usr\/src\/app\/dist -v .\/apps:\/usr\/src\/app\/apps -v .\/libs:\/usr\/src\/app\/libs ${REGISTRY}\/${BUILDER_IMAGE_NAME}:${ROOT_VERSION}<\/p>\n<p># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<br \/>\nexport IMG=${REGISTRY}\/${BASE_SERVER_IMAGE_NAME}:${ROOT_VERSION} &amp;&amp; [ -n &#8220;$(docker images -q $IMG)&#8221; ] || docker build &#8211;network host -t &#8220;${REGISTRY}\/${BASE_SERVER_IMAGE_NAME}:${ROOT_VERSION}&#8221; -t &#8220;${REGISTRY}\/${BASE_SERVER_IMAGE_NAME}:latest&#8221; -f .\/.docker\/base-server.Dockerfile . &#8211;progress=plain<\/p>\n<p># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<br \/>\nexport IMG=${REGISTRY}\/${SERVER_IMAGE_NAME}:${SERVER_VERSION} &amp;&amp; [ -n &#8220;$(docker images -q $IMG)&#8221; ] || docker build &#8211;network host -t &#8220;${REGISTRY}\/${SERVER_IMAGE_NAME}:${SERVER_VERSION}&#8221; -t &#8220;${REGISTRY}\/${SERVER_IMAGE_NAME}:latest&#8221; -f .\/.docker\/server.Dockerfile . &#8211;progress=plain &#8211;build-arg=\\&#8221;BASE_SERVER_IMAGE_TAG=${ROOT_VERSION}\\&#8221;<\/p>\n<p># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<br \/>\nexport IMG=${REGISTRY}\/${MIGRATIONS_IMAGE_NAME}:${ROOT_VERSION} &amp;&amp; [ -n &#8220;$(docker images -q $IMG)&#8221; ] || docker build &#8211;network host -t &#8220;${REGISTRY}\/${MIGRATIONS_IMAGE_NAME}:${ROOT_VERSION}&#8221; -t &#8220;${REGISTRY}\/${MIGRATIONS_IMAGE_NAME}:latest&#8221; -f .\/.docker\/migrations.Dockerfile . &#8211;progress=plain<\/p>\n<p># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<br \/>\nexport IMG=${REGISTRY}\/${NGINX_IMAGE_NAME}:${CLIENT_VERSION} &amp;&amp; [ -n &#8220;$(docker images -q $IMG)&#8221; ] || docker build &#8211;network host -t &#8220;${REGISTRY}\/${NGINX_IMAGE_NAME}:${CLIENT_VERSION}&#8221; -t &#8220;${REGISTRY}\/${NGINX_IMAGE_NAME}:latest&#8221; -f .\/.docker\/nginx.Dockerfile . &#8211;progress=plain<\/p>\n<p># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<br \/>\nexport IMG=${REGISTRY}\/${E2E_TESTS_IMAGE_NAME}:${ROOT_VERSION} &amp;&amp; [ -n &#8220;$(docker images -q $IMG)&#8221; ] || docker build &#8211;network host -t &#8220;${REGISTRY}\/${E2E_TESTS_IMAGE_NAME}:${ROOT_VERSION}&#8221; -t &#8220;${REGISTRY}\/${E2E_TESTS_IMAGE_NAME}:latest&#8221; -f .\/.docker\/e2e-tests.Dockerfile . &#8211;progress=plain<\/p>\n<p>  10. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0628\u0631\u0627\u06cc \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0645\u062d\u0644\u06cc \u062d\u0627\u0644\u062a &#8220;Docker Compose&#8221;.<\/p>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0641\u0627\u06cc\u0644 .docker\/docker-compose-full.yml<\/p>\n<p>version: &#8216;3&#8217;<br \/>\nnetworks:<br \/>\n  nestjs-mod-fullstack-network:<br \/>\n    driver: &#8216;bridge&#8217;<br \/>\nservices:<br \/>\n  nestjs-mod-fullstack-postgre-sql:<br \/>\n    image: &#8216;bitnami\/postgresql:15.5.0&#8217;<br \/>\n    container_name: &#8216;nestjs-mod-fullstack-postgre-sql&#8217;<br \/>\n    networks:<br \/>\n      &#8211; &#8216;nestjs-mod-fullstack-network&#8217;<br \/>\n    healthcheck:<br \/>\n      test:<br \/>\n        &#8211; &#8216;CMD-SHELL&#8217;<br \/>\n        &#8211; &#8216;pg_isready -U postgres&#8217;<br \/>\n      interval: &#8216;5s&#8217;<br \/>\n      timeout: &#8216;5s&#8217;<br \/>\n      retries: 5<br \/>\n    tty: true<br \/>\n    restart: &#8216;always&#8217;<br \/>\n    environment:<br \/>\n      POSTGRESQL_USERNAME: &#8216;${SERVER_POSTGRE_SQL_POSTGRESQL_USERNAME}&#8217;<br \/>\n      POSTGRESQL_PASSWORD: &#8216;${SERVER_POSTGRE_SQL_POSTGRESQL_PASSWORD}&#8217;<br \/>\n      POSTGRESQL_DATABASE: &#8216;${SERVER_POSTGRE_SQL_POSTGRESQL_DATABASE}&#8217;<br \/>\n    volumes:<br \/>\n      &#8211; &#8216;nestjs-mod-fullstack-postgre-sql-volume:\/bitnami\/postgresql&#8217;<br \/>\n  nestjs-mod-fullstack-postgre-sql-migrations:<br \/>\n    image: &#8216;ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-migrations:${ROOT_VERSION}&#8217;<br \/>\n    container_name: &#8216;nestjs-mod-fullstack-postgre-sql-migrations&#8217;<br \/>\n    networks:<br \/>\n      &#8211; &#8216;nestjs-mod-fullstack-network&#8217;<br \/>\n    tty: true<br \/>\n    environment:<br \/>\n      NX_SKIP_NX_CACHE: &#8216;true&#8217;<br \/>\n      SERVER_ROOT_DATABASE_URL: &#8216;${SERVER_ROOT_DATABASE_URL}&#8217;<br \/>\n      SERVER_APP_DATABASE_URL: &#8216;${SERVER_APP_DATABASE_URL}&#8217;<br \/>\n    depends_on:<br \/>\n      nestjs-mod-fullstack-postgre-sql:<br \/>\n        condition: &#8216;service_healthy&#8217;<br \/>\n    working_dir: &#8216;\/usr\/src\/app&#8217;<br \/>\n    volumes:<br \/>\n      &#8211; &#8216;.\/..\/apps:\/usr\/src\/app\/apps&#8217;<br \/>\n      &#8211; &#8216;.\/..\/libs:\/usr\/src\/app\/libs&#8217;<br \/>\n  nestjs-mod-fullstack-server:<br \/>\n    image: &#8216;ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-server:${SERVER_VERSION}&#8217;<br \/>\n    container_name: &#8216;nestjs-mod-fullstack-server&#8217;<br \/>\n    networks:<br \/>\n      &#8211; &#8216;nestjs-mod-fullstack-network&#8217;<br \/>\n    healthcheck:<br \/>\n      test: [&#8216;CMD-SHELL&#8217;, &#8216;npx -y wait-on &#8211;timeout= &#8211;interval=1000 &#8211;window &#8211;verbose &#8211;log http:\/\/localhost:${SERVER_PORT}\/api\/health&#8217;]\n      interval: 30s<br \/>\n      timeout: 10s<br \/>\n      retries: 10<br \/>\n    tty: true<br \/>\n    environment:<br \/>\n      SERVER_APP_DATABASE_URL: &#8216;${SERVER_APP_DATABASE_URL}&#8217;<br \/>\n      SERVER_PORT: &#8216;${SERVER_PORT}&#8217;<br \/>\n    restart: &#8216;always&#8217;<br \/>\n    depends_on:<br \/>\n      nestjs-mod-fullstack-postgre-sql:<br \/>\n        condition: service_healthy<br \/>\n      nestjs-mod-fullstack-postgre-sql-migrations:<br \/>\n        condition: service_completed_successfully<br \/>\n  nestjs-mod-fullstack-nginx:<br \/>\n    image: &#8216;ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-nginx:${CLIENT_VERSION}&#8217;<br \/>\n    container_name: &#8216;nestjs-mod-fullstack-nginx&#8217;<br \/>\n    networks:<br \/>\n      &#8211; &#8216;nestjs-mod-fullstack-network&#8217;<br \/>\n    healthcheck:<br \/>\n      test: [&#8216;CMD-SHELL&#8217;, &#8216;curl -so \/dev\/null http:\/\/localhost:${NGINX_PORT} || exit 1&#8217;]\n      interval: 30s<br \/>\n      timeout: 10s<br \/>\n      retries: 10<br \/>\n    environment:<br \/>\n      SERVER_PORT: &#8216;${SERVER_PORT}&#8217;<br \/>\n      NGINX_PORT: &#8216;${NGINX_PORT}&#8217;<br \/>\n    restart: &#8216;always&#8217;<br \/>\n    depends_on:<br \/>\n      nestjs-mod-fullstack-server:<br \/>\n        condition: service_healthy<br \/>\n    ports:<br \/>\n      &#8211; &#8216;${NGINX_PORT}:${NGINX_PORT}&#8217;<br \/>\n  nestjs-mod-fullstack-e2e-tests:<br \/>\n    image: &#8216;ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-e2e-tests:${ROOT_VERSION}&#8217;<br \/>\n    container_name: &#8216;nestjs-mod-fullstack-e2e-tests&#8217;<br \/>\n    networks:<br \/>\n      &#8211; &#8216;nestjs-mod-fullstack-network&#8217;<br \/>\n    environment:<br \/>\n      BASE_URL: &#8216;http:\/\/nestjs-mod-fullstack-nginx:${NGINX_PORT}&#8217;<br \/>\n    depends_on:<br \/>\n      nestjs-mod-fullstack-nginx:<br \/>\n        condition: service_healthy<br \/>\n    working_dir: &#8216;\/usr\/src\/app&#8217;<br \/>\n    volumes:<br \/>\n      &#8211; &#8216;.\/..\/apps:\/usr\/src\/app\/apps&#8217;<br \/>\n      &#8211; &#8216;.\/..\/libs:\/usr\/src\/app\/libs&#8217;<br \/>\n  nestjs-mod-fullstack-https-portal:<br \/>\n    image: steveltn\/https-portal:1<br \/>\n    container_name: &#8216;nestjs-mod-fullstack-https-portal&#8217;<br \/>\n    networks:<br \/>\n      &#8211; &#8216;nestjs-mod-fullstack-network&#8217;<br \/>\n    ports:<br \/>\n      &#8211; &#8217;80:80&#8242;<br \/>\n      &#8211; &#8216;443:443&#8217;<br \/>\n    links:<br \/>\n      &#8211; nestjs-mod-fullstack-nginx<br \/>\n    restart: always<br \/>\n    environment:<br \/>\n      STAGE: &#8216;${HTTPS_PORTAL_STAGE}&#8217;<br \/>\n      DOMAINS: &#8216;${SERVER_DOMAIN} -&gt; http:\/\/nestjs-mod-fullstack-nginx:${NGINX_PORT}&#8217;<br \/>\n    depends_on:<br \/>\n      nestjs-mod-fullstack-nginx:<br \/>\n        condition: service_healthy<br \/>\n    volumes:<br \/>\n      &#8211; nestjs-mod-fullstack-https-portal-volume:\/var\/lib\/https-portal<br \/>\nvolumes:<br \/>\n  nestjs-mod-fullstack-postgre-sql-volume:<br \/>\n    name: &#8216;nestjs-mod-fullstack-postgre-sql-volume&#8217;<br \/>\n  nestjs-mod-fullstack-https-portal-volume:<br \/>\n    name: &#8216;nestjs-mod-fullstack-https-portal-volume&#8217;<\/p>\n<p>  11. \u062d\u0627\u0644\u062a \u0645\u062d\u0644\u06cc &#8220;Docker Compose&#8221; \u0631\u0627 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645 \u0648 \u0645\u0646\u062a\u0638\u0631 \u062a\u06a9\u0645\u06cc\u0644 \u0645\u0648\u0641\u0642\u06cc\u062a \u0622\u0645\u06cc\u0632 \u062a\u0633\u062a \u0647\u0627 \u0647\u0633\u062a\u06cc\u0645<\/p>\n<p>\u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u0632\u06cc\u0627\u062f\u06cc \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc \u062f\u0647\u06cc\u0645 \u06cc\u0627 \u067e\u0627\u0631\u0627\u0645\u062a\u0631\u0647\u0627\u06cc devops \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc \u062f\u0647\u06cc\u0645 \u06cc\u0627 \u0648\u0627\u0628\u0633\u062a\u06af\u06cc \u0647\u0627\u06cc \u062c\u062f\u06cc\u062f \u0646\u0635\u0628 \u0645\u06cc \u06a9\u0646\u06cc\u0645\u060c \u0628\u0627\u06cc\u062f \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u0645\u0637\u0645\u0626\u0646 \u0634\u0648\u06cc\u0645 \u06a9\u0647 \u0647\u0645\u0647 \u0686\u06cc\u0632 \u062f\u0631 \u062d\u0627\u0644\u062a &#8220;Docker Compose&#8221; \u06a9\u0627\u0631 \u0645\u06cc \u06a9\u0646\u062f\u060c \u0632\u06cc\u0631\u0627 \u0641\u0631\u0622\u06cc\u0646\u062f \u0633\u0627\u062e\u062a \u062f\u0631 CI\/CD \u0645\u062d\u062f\u0648\u062f\u06cc\u062a \u0647\u0627\u06cc \u0631\u0627\u06cc\u06af\u0627\u0646 \u0631\u0627 \u062f\u0631 \u0645\u0648\u0627\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0635\u0631\u0641 \u0645\u06cc \u06a9\u0646\u062f. \u062f\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0639\u0645\u0648\u0645\u06cc\u060c \u0648 \u0647\u0645\u0686\u0646\u06cc\u0646 \u0647\u0646\u06af\u0627\u0645 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u062f\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u06a9\u0645 \u0645\u0635\u0631\u0641 \u062e\u0648\u062f\u060c \u0641\u0631\u0622\u06cc\u0646\u062f \u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0631\u0627 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0648 \u0627\u0641\u0632\u0627\u06cc\u0634 \u0645\u06cc \u062f\u0647\u062f.<\/p>\n<p>\u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0645\u062d\u0644\u06cc \u062f\u0631 \u062d\u0627\u0644\u062a &#8220;Docker Compose&#8221; \u0647\u0645\u0686\u0646\u06cc\u0646 \u0628\u0647 \u0634\u0645\u0627 \u0627\u0645\u06a9\u0627\u0646 \u0645\u06cc \u062f\u0647\u062f \u0645\u0634\u06a9\u0644\u0627\u062a\u06cc \u0631\u0627 \u06a9\u0647 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0647\u0646\u06af\u0627\u0645 \u0627\u062c\u0631\u0627 \u0627\u0632 \u0637\u0631\u06cc\u0642 Kubernetes \u0638\u0627\u0647\u0631 \u0634\u0648\u0646\u062f \u0634\u0646\u0627\u0633\u0627\u06cc\u06cc \u06a9\u0646\u06cc\u062f\u060c \u0632\u06cc\u0631\u0627 \u0645\u0648\u0646\u062a\u0627\u0698 Docker \u062a\u0635\u0627\u0648\u06cc\u0631 \u06cc\u06a9\u0633\u0627\u0646 \u0627\u0633\u062a<\/p>\n<p>\u0648\u0642\u062a\u06cc \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u0627\u062c\u0631\u0627 \u0645\u06cc\u200c\u0634\u0648\u062f\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u0645 \u0622\u0646 \u0631\u0627 \u062f\u0627\u0646\u0644\u0648\u062f \u0648 \u0648\u0635\u0644 \u06a9\u0646\u06cc\u0645 Docker \u062a\u0635\u0627\u0648\u06cc\u0631\u06cc \u06a9\u0647 \u062f\u0631 Kubernetes \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0634\u062f\u0647\u200c\u0627\u0646\u062f\u060c \u0628\u0647 \u06cc\u0627\u0641\u062a\u0646 \u0627\u0634\u06a9\u0627\u0644\u0627\u062a\u06cc \u06a9\u0645\u06a9 \u0645\u06cc\u200c\u06a9\u0646\u062f \u06a9\u0647 \u062f\u0631 \u0645\u0627\u0634\u06cc\u0646\u200c\u0647\u0627\u06cc \u0645\u0627 \u0648 \u062f\u0631 \u0645\u0648\u0646\u062a\u0627\u0698 \u0645\u062d\u0644\u06cc \u0645\u0627 \u062a\u06a9\u0631\u0627\u0631 \u0646\u0645\u06cc\u200c\u0634\u0648\u0646\u062f. Docker \u062a\u0635\u0627\u0648\u06cc\u0631<\/p>\n<p>\u062f\u0633\u062a\u0648\u0631\u0627\u062a<\/p>\n<p>npm run docker-compose-full:prod:start<br \/>\ndocker logs nestjs-mod-fullstack-e2e-tests<\/p>\n<p>\u062e\u0631\u0648\u062c\u06cc \u0647\u0627\u06cc \u06a9\u0646\u0633\u0648\u0644<\/p>\n<p>$ docker logs nestjs-mod-fullstack-e2e-tests<\/p>\n<p>&gt; @nestjs-mod-fullstack\/source@0.0.0 test:e2e<br \/>\n&gt; .\/node_modules\/.bin\/nx run-many &#8211;exclude=@nestjs-mod-fullstack\/source &#8211;all -t=e2e &#8211;skip-nx-cache=true &#8211;output-style=stream-without-prefixes<\/p>\n<p>NX  Falling back to ts-node for local typescript execution. This may be a little slower.<br \/>\n &#8211; To fix this, ensure @swc-node\/register and @swc\/core have been installed<\/p>\n<p> NX   Running target e2e for 2 projects:<\/p>\n<p>&#8211; client-e2e<br \/>\n&#8211; server-e2e<\/p>\n<p>&gt; nx run client-e2e:e2e<\/p>\n<p>&gt; playwright test<\/p>\n<p>Running 6 tests using 3 workers<br \/>\n  6 passed (4.9s)<\/p>\n<p>To open last HTML report run:<\/p>\n<p>  npx playwright show-report ..\/..\/dist\/.playwright\/apps\/client-e2e\/playwright-report<\/p>\n<p>&gt; nx run server-e2e:e2e<\/p>\n<p>Setting up&#8230;<br \/>\n PASS   server-e2e  apps\/server-e2e\/src\/server\/server.spec.ts<br \/>\n  GET \/api<br \/>\n    \u2713 should return a message (32 ms)<br \/>\n    \u2713 should create and return a demo object (38 ms)<br \/>\n    \u2713 should get demo object by id (9 ms)<br \/>\n    \u2713 should get all demo object (7 ms)<br \/>\n    \u2713 should delete demo object by id (8 ms)<br \/>\n    \u2713 should get all demo object (6 ms)<br \/>\nTest Suites: 1 passed, 1 total<br \/>\nTests:       6 passed, 6 total<br \/>\nSnapshots:   0 total<br \/>\nTime:        0.789 s<br \/>\nRan all test suites.<br \/>\nTearing down&#8230;<\/p>\n<p> NX   Successfully ran target e2e for 2 projects<\/p>\n<p>  12. \u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u06a9\u0631\u062f\u0646 \u0686\u06a9 \u0628\u0631\u0627\u06cc \u0646\u0634\u0627\u0646\u06af\u0631 \u0627\u0646\u062a\u0634\u0627\u0631 \u062f\u0631 \u0646\u0638\u0631 commit \u0628\u0627 \u06cc\u06a9 \u0628\u0631\u0631\u0633\u06cc \u0628\u0631\u0627\u06cc \u0646\u0634\u0627\u0646\u06af\u0631 \u0627\u0646\u062a\u0634\u0627\u0631 \u067e\u0631\u0634<\/p>\n<p>\u062f\u0631 \u067e\u0633\u062a \u0642\u0628\u0644\u06cc \u0646\u0634\u0627\u0646\u06af\u0631 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0645 [release] \u0628\u0627 \u062a\u0648\u062c\u0647 \u0628\u0647 \u0627\u06cc\u0646\u06a9\u0647 \u0645\u0627 \u062f\u0631 \u0645\u0648\u0631\u062f \u0646\u06cc\u0627\u0632 \u0628\u0647 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u06cc\u06a9 \u0646\u0633\u062e\u0647 \u062a\u0635\u0645\u06cc\u0645 \u06af\u0631\u0641\u062a\u06cc\u0645\u060c \u0628\u06cc\u0634\u062a\u0631 \u0634\u0628\u06cc\u0647 \u06cc\u06a9 \u0646\u0645\u0648\u0646\u0647 \u0628\u0648\u062f\u060c \u062f\u0631 \u0648\u0627\u0642\u0639 \u0622\u0646\u0647\u0627 \u0647\u0645\u06cc\u0634\u0647 \u0646\u0648\u0634\u062a\u0646 \u0627\u06cc\u0646 \u0646\u0634\u0627\u0646\u06af\u0631 \u0631\u0627 \u0641\u0631\u0627\u0645\u0648\u0634 \u0645\u06cc \u06a9\u0646\u0646\u062f \u0648 \u0645\u062c\u0628\u0648\u0631\u0646\u062f \u06cc\u06a9 \u062a\u0639\u0647\u062f \u063a\u06cc\u0631 \u0636\u0631\u0648\u0631\u06cc \u063a\u06cc\u0631 \u0645\u0647\u0645 \u0631\u0627 \u0628\u0631\u0627\u06cc \u0627\u062c\u0628\u0627\u0631 \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 \u0646\u0633\u062e\u0647 \u0627\u0646\u062c\u0627\u0645 \u062f\u0647\u0646\u062f.<\/p>\n<p>\u0628\u0631\u0627\u06cc \u0627\u06cc\u0646\u06a9\u0647 \u0646\u0633\u062e\u0647 \u0647\u0645\u06cc\u0634\u0647 \u0634\u0631\u0648\u0639 \u0628\u0647 \u06a9\u0627\u0631 \u06a9\u0646\u062f\u060c \u0646\u0634\u0627\u0646\u06af\u0631 \u0631\u0627 \u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u06a9\u0646\u06cc\u062f [release] \u0628\u0627 [skip release] \u0648 \u0645\u0646\u0637\u0642 \u06a9\u0627\u0631 \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0647\u06cc\u062f\u060c \u062d\u0627\u0644\u0627 \u062f\u0631 \u0635\u0648\u0631\u062a \u0631\u0633\u06cc\u062f\u0646 \u0628\u0647 \u0646\u0634\u0627\u0646\u06af\u0631 \u0645\u0634\u062e\u0635 \u0634\u062f\u0647\u060c \u0627\u0632 \u0645\u0631\u062d\u0644\u0647 \u0627\u06cc\u062c\u0627\u062f \u0627\u0646\u062a\u0634\u0627\u0631 \u0645\u06cc \u06af\u0630\u0631\u06cc\u0645.<\/p>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0641\u0627\u06cc\u0644 .github\/workflows\/kubernetes.yml<\/p>\n<p>name: &#8216;Kubernetes&#8217;<\/p>\n<p>on:<br \/>\n  push:<br \/>\n    branches: [&#8216;master&#8217;]\nenv:<br \/>\n  REGISTRY: ghcr.io<br \/>\n  BASE_SERVER_IMAGE_NAME: ${{ github.repository }}-base-server<br \/>\n  BUILDER_IMAGE_NAME: ${{ github.repository }}-builder<br \/>\n  MIGRATIONS_IMAGE_NAME: ${{ github.repository }}-migrations<br \/>\n  SERVER_IMAGE_NAME: ${{ github.repository }}-server<br \/>\n  NGINX_IMAGE_NAME: ${{ github.repository }}-nginx<br \/>\n  E2E_TESTS_IMAGE_NAME: ${{ github.repository }}-e2e-tests<br \/>\n  COMPOSE_INTERACTIVE_NO_CLI: 1<br \/>\n  NX_DAEMON: false<br \/>\n  NX_PARALLEL: false<br \/>\n  NX_SKIP_NX_CACHE: true<br \/>\n  DISABLE_SERVE_STATIC: true<br \/>\njobs:<br \/>\n  release:<br \/>\n    runs-on: ubuntu-latest<br \/>\n    permissions:<br \/>\n      contents: write # to be able to publish a GitHub release<br \/>\n      issues: write # to be able to comment on released issues<br \/>\n      pull-requests: write # to be able to comment on released pull requests<br \/>\n      id-token: write # to enable use of OIDC for npm provenance<br \/>\n    steps:<br \/>\n      &#8211; uses: actions\/checkout@v4<br \/>\n        if: ${{ !contains(github.event.head_commit.message, &#8216;[skip release]&#8217;) }}<br \/>\n      &#8211; run: npm install &#8211;prefer-offline &#8211;no-audit &#8211;progress=false<br \/>\n        if: ${{ !contains(github.event.head_commit.message, &#8216;[skip release]&#8217;) }}<br \/>\n      &#8211; run: npm run nx &#8212; run-many &#8211;target=semantic-release &#8211;all &#8211;parallel=false<br \/>\n        if: ${{ !contains(github.event.head_commit.message, &#8216;[skip release]&#8217;) }}<br \/>\n        env:<br \/>\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}<br \/>\n# &#8230;<\/p>\n<p>  13. \u0627\u0641\u0632\u0648\u062f\u0646 \u0633\u062e\u062a\u06af\u06cc\u0631\u06cc \u0628\u0647 \u06a9\u062f<\/p>\n<p>\u0639\u0644\u0627\u0648\u0647 \u0628\u0631 lint-staged \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0628\u0631\u0627\u06cc \u0622\u0648\u0631\u062f\u0646 \u06a9\u062f \u0628\u0647 \u06cc\u06a9 \u0633\u0628\u06a9 \u0645\u0634\u062a\u0631\u06a9\u060c \u0647\u0645\u0686\u0646\u06cc\u0646 \u0644\u0627\u0632\u0645 \u0627\u0633\u062a \u0645\u0634\u062a\u0631\u06a9 \u0628\u0627\u0634\u062f eslint \u0648 typescript-CompilerOptions \u067e\u0627\u0631\u0627\u0645\u062a\u0631\u0647\u0627 \u0628\u0627 \u0642\u0648\u0627\u0646\u06cc\u0646 \u0633\u062e\u062a\u06af\u06cc\u0631\u06cc \u06a9\u062f \u0627\u0636\u0627\u0641\u06cc.<\/p>\n<p>\u0645\u0646 \u0645\u0639\u0645\u0648\u0644\u0627\u064b \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0631\u0627 \u0644\u0645\u0633 \u0646\u0645\u06cc \u06a9\u0646\u0645 eslint \u0648 prettier \u062a\u0646\u0638\u06cc\u0645\u0627\u062a\u060c \u0641\u0642\u0637 \u06a9\u0645\u06cc \u0633\u062e\u062a\u06af\u06cc\u0631\u06cc \u0631\u0627 \u0628\u0647 \u0631\u06cc\u0634\u0647 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f Typescript \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc<\/p>\n<p>\u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u0642\u0648\u0627\u0646\u06cc\u0646 \u0627\u0636\u0627\u0641\u06cc \u0628\u0647 tsconfig.base.json<\/p>\n<p>{<br \/>\n  \/\/ &#8230;<br \/>\n  &#8220;compilerOptions&#8221;: {<br \/>\n    \/\/ &#8230;<br \/>\n    &#8220;allowSyntheticDefaultImports&#8221;: true,<br \/>\n    &#8220;strictNullChecks&#8221;: true,<br \/>\n    &#8220;noImplicitOverride&#8221;: true,<br \/>\n    &#8220;strictPropertyInitialization&#8221;: true,<br \/>\n    &#8220;noImplicitReturns&#8221;: true,<br \/>\n    &#8220;noFallthroughCasesInSwitch&#8221;: true,<br \/>\n    &#8220;esModuleInterop&#8221;: true,<br \/>\n    &#8220;noImplicitAny&#8221;: false<br \/>\n    \/\/ &#8230;<br \/>\n  }<br \/>\n  \/\/ &#8230;<br \/>\n}<\/p>\n<p>\u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f npm run manual:prepare \u0648 \u0647\u0631 \u0686\u06cc\u0632\u06cc \u06a9\u0647 \u062e\u0631\u0627\u0628 \u0627\u0633\u062a \u0631\u0627 \u0627\u0635\u0644\u0627\u062d \u06a9\u0646\u06cc\u062f \u0648 \u062f\u0648\u0628\u0627\u0631\u0647 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u06a9\u0646\u06cc\u062f \u062a\u0627 \u062a\u0645\u0627\u0645 \u062e\u0637\u0627\u0647\u0627 \u0631\u0627 \u0628\u0631\u0637\u0631\u0641 \u06a9\u0646\u06cc\u0645.<\/p>\n<p>  14. \u06a9\u062f \u0631\u0627 \u0645\u062a\u0639\u0647\u062f \u06a9\u0646\u06cc\u062f \u0648 \u0645\u0646\u062a\u0638\u0631 \u0627\u06cc\u062c\u0627\u062f \u0645\u0648\u0641\u0642\u06cc\u062a \u0622\u0645\u06cc\u0632 \u0646\u0633\u062e\u0647 \u0647\u0627 \u0648 \u06af\u0630\u0631\u0627\u0646\u062f\u0646 \u062a\u0633\u062a \u0647\u0627 \u0628\u0627\u0634\u06cc\u062f<\/p>\n<p>\u0646\u062a\u06cc\u062c\u0647 \u0641\u0639\u0644\u06cc \u0639\u0645\u0644\u06cc\u0627\u062a CI\/CD: https:\/\/github.com\/nestjs-mod\/nestjs-mod-fullstack\/actions\/runs\/10904254598<br \/>\n\u0633\u0627\u06cc\u062a \u0641\u0639\u0644\u06cc: https:\/\/fullstack.nestjs-mod.com<\/p>\n<p>  \u0646\u062a\u06cc\u062c\u0647 \u06af\u06cc\u0631\u06cc<\/p>\n<p>\u0627\u06af\u0631 \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u062f\u06cc\u06af\u0631\u06cc \u062f\u0631 \u067e\u0631\u0648\u0698\u0647 \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f \u06a9\u0647 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0628\u0633\u062a\u0647 \u0628\u0647 \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0645\u062d\u06cc\u0637 \u062a\u0648\u0633\u0639\u0647 \u062a\u063a\u06cc\u06cc\u0631 \u06a9\u0646\u062f\u060c \u0627\u06cc\u0646 \u0641\u0627\u06cc\u0644 \u0647\u0627 \u0646\u06cc\u0632 \u0628\u0627\u06cc\u062f \u062f\u0631 lint-staged \u0642\u0648\u0627\u0646\u06cc\u0646.<\/p>\n<p>\u0633\u062e\u062a\u06cc \u0631\u0627 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646 \u062d\u062a\u06cc \u0642\u0648\u06cc\u200c\u062a\u0631 \u06a9\u0631\u062f\u060c \u0648 \u0647\u0645\u0686\u0646\u06cc\u0646 eslint \u0642\u0648\u0627\u0646\u06cc\u0646\u060c \u0627\u0645\u0627 \u0647\u0631 \u0628\u0627\u0631 \u0628\u0627\u06cc\u062f \u0632\u0645\u0627\u0646 \u0627\u062c\u0631\u0627 \u0631\u0627 \u0627\u0646\u062f\u0627\u0632\u0647 \u06af\u06cc\u0631\u06cc \u06a9\u0646\u06cc\u062f\u060c \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644\u060c eslint \u0642\u0627\u0646\u0648\u0646 \u0645\u0631\u062a\u0628 \u0633\u0627\u0632\u06cc \u0648\u0627\u0631\u062f\u0627\u062a \u0627\u062c\u0631\u0627 \u0645\u06cc \u0634\u0648\u062f ast \u0645\u0634\u0627\u0647\u062f\u0647 \u062a\u062c\u0632\u06cc\u0647 \u06a9\u0646\u0646\u062f\u0647\u060c \u062f\u0631 \u06cc\u06a9 \u067e\u0631\u0648\u0698\u0647 \u0628\u0632\u0631\u06af \u0641\u0642\u0637 \u0628\u0631\u0627\u06cc \u0645\u062f\u062a \u0637\u0648\u0644\u0627\u0646\u06cc \u06a9\u0627\u0631 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<p>\u062f\u0631 \u0627\u06cc\u0646 \u067e\u0633\u062a \u0646\u0634\u0627\u0646 \u062f\u0627\u062f\u0645 \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0627 \u0646\u0633\u062e\u0647\u200c\u0633\u0627\u0632\u06cc \u0641\u0631\u0627\u0646\u062a\u200c\u0627\u0646\u062f \u0633\u0631\u0639\u062a \u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0631\u0627 \u0627\u0641\u0632\u0627\u06cc\u0634 \u062f\u0647\u06cc\u062f \u0648 \u0647\u0645\u06cc\u0646 \u06a9\u0627\u0631 \u0631\u0627 \u0628\u0627 \u0645\u06cc\u06a9\u0631\u0648\u0633\u0631\u0648\u06cc\u0633\u200c\u0647\u0627 \u0646\u06cc\u0632 \u0627\u0646\u062c\u0627\u0645 \u062f\u0647\u06cc\u062f.<\/p>\n<p>  \u0637\u0631\u062d \u0647\u0627<\/p>\n<p>\u0627\u0632 \u0622\u0646\u062c\u0627\u06cc\u06cc \u06a9\u0647 \u0645\u0646 \u0645\u0648\u0641\u0642 \u0628\u0647 \u062a\u06a9\u0645\u06cc\u0644 \u0646\u06a9\u0627\u062a \u0627\u0635\u0644\u06cc \u062f\u0631 devops \u0634\u062f\u0645\u060c \u067e\u0633\u062a\u200c\u0647\u0627\u06cc \u0632\u06cc\u0631 \u0642\u0628\u0644\u0627\u064b \u062d\u0627\u0648\u06cc \u062a\u0648\u0636\u06cc\u062d\u0627\u062a \u0645\u062e\u062a\u0635\u0631\u06cc \u0627\u0632 \u062a\u0648\u0633\u0639\u0647 \u0648\u06cc\u0698\u06af\u06cc\u200c\u0647\u0627\u06cc \u0627\u0635\u0644\u06cc \u0627\u0633\u062a \u06a9\u0647 \u0642\u0635\u062f \u0627\u0646\u062c\u0627\u0645 \u0622\u0646 \u0631\u0627 \u062f\u0627\u0634\u062a\u0645.<\/p>\n<p>\u062f\u0631 \u067e\u0633\u062a \u0628\u0639\u062f\u06cc\u060c \u06cc\u06a9 \u0645\u0627\u0698\u0648\u0644 webhook \u062f\u0631 NestJS \u0627\u06cc\u062c\u0627\u062f \u062e\u0648\u0627\u0647\u0645 \u06a9\u0631\u062f \u062a\u0627 \u0627\u0639\u0644\u0627\u0646\u200c\u0647\u0627\u06cc\u06cc \u062f\u0631 \u0645\u0648\u0631\u062f \u0631\u0648\u06cc\u062f\u0627\u062f\u0647\u0627\u06cc\u0645\u0627\u0646 \u0628\u0647 \u0633\u0631\u0648\u06cc\u0633\u200c\u0647\u0627\u06cc \u0634\u062e\u0635 \u062b\u0627\u0644\u062b \u0627\u0631\u0627\u0626\u0647 \u06a9\u0646\u062f&#8230;<\/p>\n<p>  \u067e\u06cc\u0648\u0646\u062f\u0647\u0627<\/p>\n<p>https:\/\/nestjs.com &#8211; \u0648\u0628 \u0633\u0627\u06cc\u062a \u0631\u0633\u0645\u06cc \u0686\u0627\u0631\u0686\u0648\u0628<br \/>\nhttps:\/\/nestjs-mod.com &#8211; \u0648\u0628 \u0633\u0627\u06cc\u062a \u0631\u0633\u0645\u06cc \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u0627\u0636\u0627\u0641\u06cc<br \/>\nhttps:\/\/fullstack.nestjs-mod.com &#8211; \u0648\u0628 \u0633\u0627\u06cc\u062a \u0627\u0632 \u067e\u0633\u062a<br \/>\nhttps:\/\/github.com\/nestjs-mod\/nestjs-mod-fullstack &#8211; \u067e\u0631\u0648\u0698\u0647 \u0627\u0632 \u067e\u0633\u062a<br \/>\nhttps:\/\/github.com\/nestjs-mod\/nestjs-mod-fullstack\/compare\/2f9b6eddb32a9777fabda81afa92d9aaebd432cc..460257364bb4ce8e23fe761fb21c9ca74 &#8211; \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0641\u0639\u0644\u06cc<\/p>\n<p>\u0627\u0632 \u0632\u0645\u0627\u0646\u06cc \u06a9\u0647 \u0646\u0633\u062e\u0647 \u0627\u0632 \u0637\u0631\u06cc\u0642 <code>nx-semantic-release<\/code> \u0627\u0641\u0632\u0648\u0646\u0647 \u0628\u0627 \u062a\u062c\u0632\u06cc\u0647 \u0648 \u062a\u062d\u0644\u06cc\u0644 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0645\u0631\u0628\u0648\u0637 \u0628\u0647 \u0622\u0646 \u0635\u0648\u0631\u062a \u0645\u06cc \u06af\u06cc\u0631\u062f <code>Typescript<\/code> \u0648\u0627\u0631\u062f\u0627\u062a\u060c \u0628\u0627\u06cc\u062f \u0627\u06cc\u0646 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0631\u0627 \u0628\u0647 \u062d\u062f\u0627\u0642\u0644 \u0628\u0631\u0633\u0627\u0646\u06cc\u0645\u060c \u0628\u0631\u0627\u06cc \u0627\u0646\u062c\u0627\u0645 \u0627\u06cc\u0646 \u06a9\u0627\u0631\u060c \u0628\u0647 \u067e\u0631\u0648\u0698\u0647 https:\/\/www.npmjs.com\/package\/lint-staged \u0645\u062a\u0635\u0644 \u0645\u06cc \u0634\u0648\u06cc\u0645 \u0648 \u0633\u062e\u062a \u06af\u06cc\u0631\u06cc \u0631\u0627 \u0628\u0647 \u0622\u0646 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645. <code>Typescript<\/code> \u06a9\u062f<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter-rtl ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"\u062a\u063a\u06cc\u06cc\u0631 \u0648\u0636\u0639\u06cc\u062a \u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#1_%D8%A7%D8%B6%D8%A7%D9%81%D9%87_%DA%A9%D8%B1%D8%AF%D9%86_lint-staged_%D8%A8%D8%B1%D8%A7%DB%8C_%D9%82%D8%A7%D9%84%D8%A8_%D8%A8%D9%86%D8%AF%DB%8C_%DA%A9%D8%AF_%D9%87%D9%86%DA%AF%D8%A7%D9%85_%D8%A7%D9%86%D8%AC%D8%A7%D9%85\" >1. \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 lint-staged \u0628\u0631\u0627\u06cc \u0642\u0627\u0644\u0628 \u0628\u0646\u062f\u06cc \u06a9\u062f \u0647\u0646\u06af\u0627\u0645 \u0627\u0646\u062c\u0627\u0645<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#2_%D9%85%D8%A7_%D8%AF%D8%B1_%D8%AD%D8%A7%D9%84_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA_%D8%A2%D9%85%D8%A7%D8%AF%D9%87_%D9%88_%D8%A8%D8%AE%D8%B4_lint-staged_%D8%AF%D8%B1_root_packagejson_%D9%87%D8%B3%D8%AA%DB%8C%D9%85\" >2. \u0645\u0627 \u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0622\u0645\u0627\u062f\u0647 \u0648 \u0628\u062e\u0634 lint-staged \u062f\u0631 root package.json \u0647\u0633\u062a\u06cc\u0645.<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#3_%D9%82%D8%A7%D9%84%D8%A8_%D8%A8%D9%86%D8%AF%DB%8C_%D9%85%D8%B1%D8%AD%D9%84%D9%87_%D9%BE%D8%B1%D8%B2_%D8%B1%D8%A7_%D8%A8%D9%87_%D8%B5%D9%88%D8%B1%D8%AA_%D8%AF%D8%B3%D8%AA%DB%8C_%D8%B4%D8%B1%D9%88%D8%B9_%DA%A9%D9%86%DB%8C%D8%AF\" >3. \u0642\u0627\u0644\u0628 \u0628\u0646\u062f\u06cc \u0645\u0631\u062d\u0644\u0647 \u067e\u0631\u0632 \u0631\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u062f\u0633\u062a\u06cc \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#4_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_packagejson_%D9%88_NX_%D8%AF%D8%B1_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87_%D9%87%D8%A7%DB%8C_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D8%AF%DB%8C\" >4. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc package.json \u0648 NX \u062f\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 \u0647\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#5_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%DB%8C%DA%A9_packagejson_%D8%AF%D8%B1_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87_frontend_%D9%88_%D8%A7%D8%B6%D8%A7%D9%81%D9%87_%DA%A9%D8%B1%D8%AF%D9%86_%D8%AF%D8%B3%D8%AA%D9%88%D8%B1_semantic-release_%D8%A8%D9%87_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_NX_%D8%A2%D9%86\" >5. \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 package.json \u062f\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 frontend \u0648 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u062f\u0633\u062a\u0648\u0631 semantic-release \u0628\u0647 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc NX \u0622\u0646<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#6_%D8%A7%D9%81%D8%B2%D9%88%D8%AF%D9%86_%DB%8C%DA%A9_%D9%85%D8%AA%D8%BA%DB%8C%D8%B1_%D9%85%D8%AD%DB%8C%D8%B7_%D9%BE%D9%88%DB%8C%D8%A7_%D8%AC%D8%AF%DB%8C%D8%AF\" >6. \u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0645\u062a\u063a\u06cc\u0631 \u0645\u062d\u06cc\u0637 \u067e\u0648\u06cc\u0627 \u062c\u062f\u06cc\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#7_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D8%A7%D8%B3%D8%AA%D9%82%D8%B1%D8%A7%D8%B1_%D9%81%D8%A7%DB%8C%D9%84\" >7. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0641\u0627\u06cc\u0644<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#8_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_%D8%A7%D8%B3%D8%AA%D9%82%D8%B1%D8%A7%D8%B1_CICD_%D8%A8%D8%B1%D8%A7%DB%8C_Kubernetes_%D9%88_Docker_Compose\" >8. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0627\u0633\u062a\u0642\u0631\u0627\u0631 CI\/CD \u0628\u0631\u0627\u06cc Kubernetes \u0648 Docker Compose<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#9_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D8%AC%D9%85%D8%B9_%D8%A2%D9%88%D8%B1%DB%8C_%DA%A9%D9%86%D9%86%D8%AF%D9%87_%D8%AA%D8%B5%D9%88%DB%8C%D8%B1_%D9%85%D8%AD%D9%84%DB%8C_Docker\" >9. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u062c\u0645\u0639 \u0622\u0648\u0631\u06cc \u06a9\u0646\u0646\u062f\u0647 \u062a\u0635\u0648\u06cc\u0631 \u0645\u062d\u0644\u06cc Docker<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#10_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%D9%85%D8%AD%D9%84%DB%8C_%D8%AD%D8%A7%D9%84%D8%AA_%E2%80%9CDocker_Compose%E2%80%9D\" >10. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0628\u0631\u0627\u06cc \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0645\u062d\u0644\u06cc \u062d\u0627\u0644\u062a &#8220;Docker Compose&#8221;.<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#11_%D8%AD%D8%A7%D9%84%D8%AA_%D9%85%D8%AD%D9%84%DB%8C_%E2%80%9CDocker_Compose%E2%80%9D_%D8%B1%D8%A7_%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%D9%85%DB%8C_%DA%A9%D9%86%DB%8C%D9%85_%D9%88_%D9%85%D9%86%D8%AA%D8%B8%D8%B1_%D8%AA%DA%A9%D9%85%DB%8C%D9%84_%D9%85%D9%88%D9%81%D9%82%DB%8C%D8%AA_%D8%A2%D9%85%DB%8C%D8%B2_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7_%D9%87%D8%B3%D8%AA%DB%8C%D9%85\" >11. \u062d\u0627\u0644\u062a \u0645\u062d\u0644\u06cc &#8220;Docker Compose&#8221; \u0631\u0627 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645 \u0648 \u0645\u0646\u062a\u0638\u0631 \u062a\u06a9\u0645\u06cc\u0644 \u0645\u0648\u0641\u0642\u06cc\u062a \u0622\u0645\u06cc\u0632 \u062a\u0633\u062a \u0647\u0627 \u0647\u0633\u062a\u06cc\u0645<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#12_%D8%AC%D8%A7%DB%8C%DA%AF%D8%B2%DB%8C%D9%86_%DA%A9%D8%B1%D8%AF%D9%86_%DA%86%DA%A9_%D8%A8%D8%B1%D8%A7%DB%8C_%D9%86%D8%B4%D8%A7%D9%86%DA%AF%D8%B1_%D8%A7%D9%86%D8%AA%D8%B4%D8%A7%D8%B1_%D8%AF%D8%B1_%D9%86%D8%B8%D8%B1_commit_%D8%A8%D8%A7_%DB%8C%DA%A9_%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C_%D8%A8%D8%B1%D8%A7%DB%8C_%D9%86%D8%B4%D8%A7%D9%86%DA%AF%D8%B1_%D8%A7%D9%86%D8%AA%D8%B4%D8%A7%D8%B1_%D9%BE%D8%B1%D8%B4\" >12. \u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u06a9\u0631\u062f\u0646 \u0686\u06a9 \u0628\u0631\u0627\u06cc \u0646\u0634\u0627\u0646\u06af\u0631 \u0627\u0646\u062a\u0634\u0627\u0631 \u062f\u0631 \u0646\u0638\u0631 commit \u0628\u0627 \u06cc\u06a9 \u0628\u0631\u0631\u0633\u06cc \u0628\u0631\u0627\u06cc \u0646\u0634\u0627\u0646\u06af\u0631 \u0627\u0646\u062a\u0634\u0627\u0631 \u067e\u0631\u0634<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#13_%D8%A7%D9%81%D8%B2%D9%88%D8%AF%D9%86_%D8%B3%D8%AE%D8%AA%DA%AF%DB%8C%D8%B1%DB%8C_%D8%A8%D9%87_%DA%A9%D8%AF\" >13. \u0627\u0641\u0632\u0648\u062f\u0646 \u0633\u062e\u062a\u06af\u06cc\u0631\u06cc \u0628\u0647 \u06a9\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#14_%DA%A9%D8%AF_%D8%B1%D8%A7_%D9%85%D8%AA%D8%B9%D9%87%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF_%D9%88_%D9%85%D9%86%D8%AA%D8%B8%D8%B1_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%D9%85%D9%88%D9%81%D9%82%DB%8C%D8%AA_%D8%A2%D9%85%DB%8C%D8%B2_%D9%86%D8%B3%D8%AE%D9%87_%D9%87%D8%A7_%D9%88_%DA%AF%D8%B0%D8%B1%D8%A7%D9%86%D8%AF%D9%86_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7_%D8%A8%D8%A7%D8%B4%DB%8C%D8%AF\" >14. \u06a9\u062f \u0631\u0627 \u0645\u062a\u0639\u0647\u062f \u06a9\u0646\u06cc\u062f \u0648 \u0645\u0646\u062a\u0638\u0631 \u0627\u06cc\u062c\u0627\u062f \u0645\u0648\u0641\u0642\u06cc\u062a \u0622\u0645\u06cc\u0632 \u0646\u0633\u062e\u0647 \u0647\u0627 \u0648 \u06af\u0630\u0631\u0627\u0646\u062f\u0646 \u062a\u0633\u062a \u0647\u0627 \u0628\u0627\u0634\u06cc\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#%D9%86%D8%AA%DB%8C%D8%AC%D9%87_%DA%AF%DB%8C%D8%B1%DB%8C\" >\u0646\u062a\u06cc\u062c\u0647 \u06af\u06cc\u0631\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#%D8%B7%D8%B1%D8%AD_%D9%87%D8%A7\" >\u0637\u0631\u062d \u0647\u0627<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/nabfollower.com\/blog\/adding-lint-staged-to-nestjs-and-angular-applications-enabling-semantic-versioning-of-the-frontend-4hpo\/#%D9%BE%DB%8C%D9%88%D9%86%D8%AF%D9%87%D8%A7\" >\u067e\u06cc\u0648\u0646\u062f\u0647\u0627<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"1_%D8%A7%D8%B6%D8%A7%D9%81%D9%87_%DA%A9%D8%B1%D8%AF%D9%86_lint-staged_%D8%A8%D8%B1%D8%A7%DB%8C_%D9%82%D8%A7%D9%84%D8%A8_%D8%A8%D9%86%D8%AF%DB%8C_%DA%A9%D8%AF_%D9%87%D9%86%DA%AF%D8%A7%D9%85_%D8%A7%D9%86%D8%AC%D8%A7%D9%85\"><\/span>\n<p>  1. \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 lint-staged \u0628\u0631\u0627\u06cc \u0642\u0627\u0644\u0628 \u0628\u0646\u062f\u06cc \u06a9\u062f \u0647\u0646\u06af\u0627\u0645 \u0627\u0646\u062c\u0627\u0645<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 \u0627\u0628\u0632\u0627\u0631 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0647\u0627\u06cc \u062e\u0627\u0635\u06cc \u0631\u0627 \u0628\u0627 \u0647\u0631 commit \u0627\u062c\u0631\u0627 \u0645\u06cc \u06a9\u0646\u062f\u060c \u0628\u0647 \u0637\u0648\u0631\u06cc \u06a9\u0647 \u0642\u0627\u0644\u0628 \u0628\u0646\u062f\u06cc \u06a9\u062f \u062f\u0631 <code>git<\/code> \u0645\u062e\u0632\u0646 \u0647\u0645\u06cc\u0634\u0647 \u06cc\u06a9\u0633\u0627\u0646 \u0627\u0633\u062a\u060c \u0645\u0647\u0645 \u0646\u06cc\u0633\u062a \u06a9\u0647 \u062a\u0648\u0633\u0639\u0647 \u062f\u0647\u0646\u062f\u0647 \u0686\u06af\u0648\u0646\u0647 \u0645\u062d\u06cc\u0637 \u062a\u0648\u0633\u0639\u0647 \u0645\u062d\u0644\u06cc \u062e\u0648\u062f \u0631\u0627 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u06a9\u0631\u062f\u0647 \u0627\u0633\u062a.<\/p>\n<p><em>\u062f\u0633\u062a\u0648\u0631\u0627\u062a<\/em>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npx mrm@2 lint-staged\n<\/code><\/pre>\n<\/div>\n<p><em>\u062e\u0631\u0648\u062c\u06cc \u0647\u0627\u06cc \u06a9\u0646\u0633\u0648\u0644<\/em>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>npx mrm@2 lint-staged\nRunning lint-staged...\nUpdate package.json\nInstalling husky...\n\nadded 1 package, removed 1 package, and audited 2765 packages <span class=\"k\">in <\/span>18s\n\n331 packages are looking <span class=\"k\">for <\/span>funding\n  run <span class=\"sb\">`<\/span>npm fund<span class=\"sb\">`<\/span> <span class=\"k\">for <\/span>details\n\n49 vulnerabilities <span class=\"o\">(<\/span>31 moderate, 18 high<span class=\"o\">)<\/span>\n\nTo address issues that <span class=\"k\">do <\/span>not require attention, run:\n  npm audit fix\n\nTo address all issues possible <span class=\"o\">(<\/span>including breaking changes<span class=\"o\">)<\/span>, run:\n  npm audit fix <span class=\"nt\">--force<\/span>\n\nSome issues need review, and may require choosing\na different dependency.\n\nRun <span class=\"sb\">`<\/span>npm audit<span class=\"sb\">`<\/span> <span class=\"k\">for <\/span>details.\nhusky - Git hooks installed\nhusky - created .husky\/pre-commit\n<\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"2_%D9%85%D8%A7_%D8%AF%D8%B1_%D8%AD%D8%A7%D9%84_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA_%D8%A2%D9%85%D8%A7%D8%AF%D9%87_%D9%88_%D8%A8%D8%AE%D8%B4_lint-staged_%D8%AF%D8%B1_root_packagejson_%D9%87%D8%B3%D8%AA%DB%8C%D9%85\"><\/span>\n<p>  2. \u0645\u0627 \u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0622\u0645\u0627\u062f\u0647 \u0648 \u0628\u062e\u0634 lint-staged \u062f\u0631 root package.json \u0647\u0633\u062a\u06cc\u0645.<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0631\u0627 <code>prepare<\/code> \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u067e\u0633 \u0627\u0632 \u0646\u0635\u0628 \u0628\u0647 \u0637\u0648\u0631 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0627\u06cc\u062c\u0627\u062f \u0645\u06cc \u0634\u0648\u062f <code>lint-staged<\/code>\u060c \u0645\u0646 \u0622\u0646 \u0631\u0627 \u062d\u0630\u0641 \u0646\u06a9\u0631\u062f\u0645\u060c \u0641\u0642\u0637 \u0631\u0648\u0634 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0631\u0627 \u06a9\u0645\u06cc \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0627\u062f\u0645\u060c \u0622\u0646 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0631\u062f\u0645 <code>npx<\/code>.<\/p>\n<p>\u062f\u0631 \u067e\u0631\u0648\u0698\u0647 \u0647\u0627\u06cc \u06a9\u0648\u0686\u06a9\u060c <code>pre-commit<\/code> \u0642\u0644\u0627\u0628 \u0628\u0627 <code>lint-staged<\/code> \u0628\u0647 \u0633\u0631\u0639\u062a \u06a9\u0627\u0631 \u0645\u06cc\u200c\u06a9\u0646\u062f\u060c \u0627\u0645\u0627 \u0627\u06af\u0631 \u067e\u0631\u0648\u0698\u0647 \u0628\u0632\u0631\u06af \u0628\u0627\u0634\u062f\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u062f \u0637\u0648\u0644\u0627\u0646\u06cc\u200c\u062a\u0631 \u06a9\u0627\u0631 \u06a9\u0646\u062f\u060c \u062f\u0631 \u0627\u06cc\u0646 \u0635\u0648\u0631\u062a \u0628\u0631\u0627\u06cc \u0647\u0645\u0647 \u062a\u0648\u0633\u0639\u0647\u200c\u062f\u0647\u0646\u062f\u06af\u0627\u0646 \u0622\u0633\u0627\u0646\u200c\u062a\u0631 \u0627\u0633\u062a \u06a9\u0647 \u0631\u0648\u06cc \u06cc\u06a9 \u0633\u0628\u06a9 \u0642\u0627\u0644\u0628\u200c\u0628\u0646\u062f\u06cc \u0645\u0634\u062a\u0631\u06a9 \u0628\u0647 \u062a\u0648\u0627\u0641\u0642 \u0628\u0631\u0633\u0646\u062f \u062a\u0627 \u062a\u0639\u062f\u0627\u062f \u0641\u0627\u06cc\u0644\u200c\u0647\u0627\u06cc\u06cc \u0631\u0627 \u06a9\u0647 \u0644\u06cc\u0646\u062a\u0631\u0647\u0627 \u0628\u0627\u06cc\u062f \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u0646\u062f\u060c \u06a9\u0627\u0647\u0634 \u062f\u0647\u0646\u062f.<\/p>\n<p>\u062f\u0631 <code>pre-commit<\/code> \u0642\u0644\u0627\u0628\u060c \u0646\u06cc\u0627\u0632\u06cc \u0628\u0647 \u062a\u062c\u0648\u06cc\u0632 \u0639\u0645\u0644\u06cc\u0627\u062a \u0633\u0646\u06af\u06cc\u0646 \u0645\u062e\u062a\u0644\u0641 \u0646\u06cc\u0633\u062a\u060c \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644: \u062a\u0648\u0644\u06cc\u062f \u0645\u0634\u062a\u0631\u06cc frontend\u060c \u0686\u0646\u06cc\u0646 \u0639\u0645\u0644\u06cc\u0627\u062a\u06cc \u0628\u0647\u062a\u0631 \u0627\u0633\u062a \u062f\u0631 <code>CI\/CD<\/code> \u06cc\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u0628\u0627 \u062f\u0633\u062a \u062f\u0631 \u0635\u0648\u0631\u062a \u0646\u06cc\u0627\u0632\u060c \u0648 \u0646\u0647 \u0628\u0631\u0627\u06cc \u0647\u0631 commit.<\/p>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0628\u062e\u0634\u06cc \u0627\u0632 <code>package.json<\/code> \u0641\u0627\u06cc\u0644\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight json\"><code><span class=\"p\">{<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"scripts\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n    <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"prepare\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"npx -y husky install\"<\/span><span class=\"w\">\n    <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n  <\/span><span class=\"p\">},<\/span><span class=\"w\">\n  <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"lint-staged\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"*.{js,ts}\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"eslint --fix\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"*.{js,ts,css,scss,md}\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"prettier --ignore-unknown --write\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"*.js\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"eslint --cache --fix\"<\/span><span class=\"w\">\n  <\/span><span class=\"p\">}<\/span><span class=\"w\">\n  <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n<\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"3_%D9%82%D8%A7%D9%84%D8%A8_%D8%A8%D9%86%D8%AF%DB%8C_%D9%85%D8%B1%D8%AD%D9%84%D9%87_%D9%BE%D8%B1%D8%B2_%D8%B1%D8%A7_%D8%A8%D9%87_%D8%B5%D9%88%D8%B1%D8%AA_%D8%AF%D8%B3%D8%AA%DB%8C_%D8%B4%D8%B1%D9%88%D8%B9_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  3. \u0642\u0627\u0644\u0628 \u0628\u0646\u062f\u06cc \u0645\u0631\u062d\u0644\u0647 \u067e\u0631\u0632 \u0631\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u062f\u0633\u062a\u06cc \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u0647 \u0645\u0646\u0638\u0648\u0631 \u0628\u0631\u0631\u0633\u06cc \u062f\u0633\u062a\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f <code>lint-staged<\/code>\u060c \u0628\u0627\u06cc\u062f \u0647\u0645\u0647 \u0641\u0627\u06cc\u0644 \u0647\u0627 \u0631\u0627 \u0628\u0647 \u0622\u0646 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f <code>stage<\/code> \u0648 \u0622\u0646 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f <code>npx<\/code>.<\/p>\n<p><em>\u062f\u0633\u062a\u0648\u0631\u0627\u062a<\/em>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>git add <span class=\"nb\">.<\/span>\nnpx lint-staged\n<\/code><\/pre>\n<\/div>\n<p><em>\u062e\u0631\u0648\u062c\u06cc \u0647\u0627\u06cc \u06a9\u0646\u0633\u0648\u0644<\/em>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code> npx lint-staged\n\u2714 Preparing lint-staged...\n\u2714 Running tasks <span class=\"k\">for <\/span>staged files...\n\u2714 Applying modifications from tasks...\n\u2714 Cleaning up temporary files...\n<\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"4_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_packagejson_%D9%88_NX_%D8%AF%D8%B1_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87_%D9%87%D8%A7%DB%8C_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D8%AF%DB%8C\"><\/span>\n<p>  4. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc package.json \u0648 NX \u062f\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 \u0647\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u0632 \u0622\u0646\u062c\u0627\u06cc\u06cc \u06a9\u0647 \u062f\u0631 \u067e\u0633\u062a \u0642\u0628\u0644\u06cc \u0627\u0646\u062a\u0634\u0627\u0631 \u062f\u0631 \u0631\u0627 \u063a\u06cc\u0631\u0641\u0639\u0627\u0644 \u06a9\u0631\u062f\u06cc\u0645 <code>npm<\/code>\u060c \u0645\u0627 \u0646\u0633\u062e\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u0627 \u062f\u0631 \u06a9\u062f \u0645\u0646\u0628\u0639 \u062a\u063a\u06cc\u06cc\u0631 \u0646\u062f\u0627\u062f\u06cc\u0645 \u062a\u0627 \u0646\u0633\u062e\u0647 \u0645\u0648\u062c\u0648\u062f \u062f\u0631 \u06a9\u062f \u0645\u0646\u0628\u0639 \u062a\u063a\u06cc\u06cc\u0631 \u06a9\u0646\u062f \u0648 \u0627\u06cc\u0646 \u0627\u0646\u062a\u0634\u0627\u0631 \u062f\u0631 <code>npm<\/code> \u0634\u0631\u0648\u0639 \u0646\u0634\u062f\u060c \u0628\u0627\u06cc\u062f \u06af\u0632\u06cc\u0646\u0647 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f <code>\"private\": true<\/code>.<\/p>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc <code>apps\/server\/package.json<\/code> \u0641\u0627\u06cc\u0644\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight json\"><code><span class=\"p\">{<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"name\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"server\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"version\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"0.0.3\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"private\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"scripts\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{},<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"dependencies\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"pm2\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"&gt;=5.3.0\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"dotenv\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"&gt;=16.3.1\"<\/span><span class=\"w\">\n  <\/span><span class=\"p\">},<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"devScripts\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"s2\">\"manual:prepare\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"serve:dev:server\"<\/span><span class=\"p\">],<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"prodScripts\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"s2\">\"manual:prepare\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"start:prod:server\"<\/span><span class=\"p\">],<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"testsScripts\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"s2\">\"test:server\"<\/span><span class=\"p\">]<\/span><span class=\"w\">\n<\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><\/code><\/pre>\n<\/div>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0628\u062e\u0634\u06cc \u0627\u0632 <code>apps\/server\/package.json<\/code> \u0641\u0627\u06cc\u0644\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight json\"><code><span class=\"p\">{<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"name\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"server\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"targets\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n    <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"semantic-release\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n      <\/span><span class=\"nl\">\"executor\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"@theunderscorer\/nx-semantic-release:semantic-release\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n      <\/span><span class=\"nl\">\"options\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n        <\/span><span class=\"nl\">\"github\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n        <\/span><span class=\"nl\">\"changelog\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n        <\/span><span class=\"nl\">\"npm\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n        <\/span><span class=\"nl\">\"tagFormat\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"server-v${VERSION}\"<\/span><span class=\"w\">\n      <\/span><span class=\"p\">}<\/span><span class=\"w\">\n    <\/span><span class=\"p\">}<\/span><span class=\"w\">\n  <\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"5_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%DB%8C%DA%A9_packagejson_%D8%AF%D8%B1_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87_frontend_%D9%88_%D8%A7%D8%B6%D8%A7%D9%81%D9%87_%DA%A9%D8%B1%D8%AF%D9%86_%D8%AF%D8%B3%D8%AA%D9%88%D8%B1_semantic-release_%D8%A8%D9%87_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_NX_%D8%A2%D9%86\"><\/span>\n<p>  5. \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 package.json \u062f\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 frontend \u0648 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u062f\u0633\u062a\u0648\u0631 semantic-release \u0628\u0647 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc NX \u0622\u0646<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0642\u0628\u0644\u0627 \u062f\u0631 \u067e\u0633\u062a \u0647\u0627\u060c \u0645\u0627 \u0631\u0627 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u06a9\u0631\u062f\u06cc\u0645 <code>Nginx<\/code> \u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u0646\u0633\u062e\u0647 \u067e\u0634\u062a\u06cc\u0628\u0627\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u062a\u063a\u06cc\u06cc\u0631 \u06a9\u0631\u062f\u060c \u0627\u0631\u062a\u0642\u0627 \u062f\u0647\u06cc\u062f.<\/p>\n<p>\u0628\u0647 \u0645\u0646\u0638\u0648\u0631 \u0628\u0631\u0627\u06cc <code>Nginx<\/code> \u062a\u0635\u0648\u06cc\u0631 \u0628\u0627 \u06cc\u06a9 \u062c\u0644\u0648\u06cc \u062a\u0639\u0628\u06cc\u0647 \u0634\u062f\u0647 \u06a9\u0647 \u0641\u0642\u0637 \u0632\u0645\u0627\u0646\u06cc \u06a9\u0647 \u0642\u0633\u0645\u062a \u0638\u0627\u0647\u0631\u06cc \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc \u06a9\u0646\u062f \u0645\u0648\u0646\u062a\u0627\u0698 \u0645\u06cc \u0634\u0648\u062f\u060c \u0628\u0627\u06cc\u062f \u0642\u0633\u0645\u062a \u062c\u0644\u0648\u06cc\u06cc \u0631\u0627 \u0646\u0633\u062e\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u0645 \u0648 \u0627\u0632 \u0646\u0633\u062e\u0647 \u0622\u0646 \u062f\u0631 \u0645\u0646\u0637\u0642 \u0647\u0627\u06cc \u0628\u0639\u062f\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u0645. <code>Docker<\/code> \u062a\u0635\u0627\u0648\u06cc\u0631 \u0648 <code>Kubernetes<\/code> \u0642\u0627\u0644\u0628 \u0647\u0627<\/p>\n<p>\u0646\u0633\u062e\u0647\u200c\u0633\u0627\u0632\u06cc \u0645\u0639\u0646\u0627\u06cc\u06cc \u0646\u06cc\u0627\u0632 \u0628\u0647 \u0627\u0644\u0641 \u062f\u0627\u0631\u062f <code>package.json<\/code> \u0628\u0631\u0627\u06cc \u06a9\u0627\u0631 \u0628\u0627 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 \u06cc\u0627 \u0628\u0631\u0646\u0627\u0645\u0647\u060c \u0628\u0646\u0627\u0628\u0631\u0627\u06cc\u0646 \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 frontend \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0647 \u0648 \u0645\u0634\u062e\u0635 \u0645\u06cc \u06a9\u0646\u06cc\u0645 <code>\"private\": true<\/code>.<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f <code>apps\/client\/package.json<\/code> \u0641\u0627\u06cc\u0644\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight json\"><code><span class=\"p\">{<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"name\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"client\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"version\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"0.0.1\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"private\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"w\">\n<\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><\/code><\/pre>\n<\/div>\n<p>\u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0647\u062f\u0641 \u062c\u062f\u06cc\u062f \u0628\u0647 <code>apps\/client\/project.json<\/code> \u0641\u0627\u06cc\u0644\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight json\"><code><span class=\"p\">{<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"name\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"client\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"targets\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n    <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"semantic-release\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n      <\/span><span class=\"nl\">\"executor\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"@theunderscorer\/nx-semantic-release:semantic-release\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n      <\/span><span class=\"nl\">\"options\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n        <\/span><span class=\"nl\">\"github\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n        <\/span><span class=\"nl\">\"changelog\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n        <\/span><span class=\"nl\">\"npm\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n        <\/span><span class=\"nl\">\"tagFormat\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"client-v${VERSION}\"<\/span><span class=\"w\">\n      <\/span><span class=\"p\">}<\/span><span class=\"w\">\n    <\/span><span class=\"p\">}<\/span><span class=\"w\">\n  <\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"6_%D8%A7%D9%81%D8%B2%D9%88%D8%AF%D9%86_%DB%8C%DA%A9_%D9%85%D8%AA%D8%BA%DB%8C%D8%B1_%D9%85%D8%AD%DB%8C%D8%B7_%D9%BE%D9%88%DB%8C%D8%A7_%D8%AC%D8%AF%DB%8C%D8%AF\"><\/span>\n<p>  6. \u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0645\u062a\u063a\u06cc\u0631 \u0645\u062d\u06cc\u0637 \u067e\u0648\u06cc\u0627 \u062c\u062f\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0645\u062a\u063a\u06cc\u0631 \u062c\u062f\u06cc\u062f \u0628\u0627 \u0646\u0633\u062e\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 frontend \u0628\u0647 \u0641\u0627\u06cc\u0644 <code>.kubernetes\/set-env.sh<\/code> \u0648 <code>.docker\/set-env.sh<\/code>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nb\">export <\/span><span class=\"nv\">CLIENT_VERSION<\/span><span class=\"o\">=<\/span><span class=\"si\">$(<\/span><span class=\"nb\">cd<\/span> .\/apps\/client <span class=\"o\">&amp;&amp;<\/span> npm pkg get version <span class=\"nt\">--workspaces<\/span><span class=\"o\">=<\/span><span class=\"nb\">false<\/span> | <span class=\"nb\">tr<\/span> <span class=\"nt\">-d<\/span> <span class=\"se\">\\\"<\/span><span class=\"si\">)<\/span>\n<\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"7_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D8%A7%D8%B3%D8%AA%D9%82%D8%B1%D8%A7%D8%B1_%D9%81%D8%A7%DB%8C%D9%84\"><\/span>\n<p>  7. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0641\u0627\u06cc\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0641\u0627\u06cc\u0644 <code>.kubernetes\/templates\/client\/3.deployment.yaml<\/code>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"na\">apiVersion<\/span><span class=\"pi\">:<\/span> <span class=\"s\">apps\/v1<\/span>\n<span class=\"na\">kind<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Deployment<\/span>\n<span class=\"na\">metadata<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">namespace<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">%NAMESPACE%'<\/span>\n  <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"err\">%<\/span><span class=\"s\">NAMESPACE%-client<\/span>\n<span class=\"na\">spec<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">replicas<\/span><span class=\"pi\">:<\/span> <span class=\"m\">1<\/span>\n  <span class=\"na\">selector<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">matchLabels<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">pod<\/span><span class=\"pi\">:<\/span> <span class=\"err\">%<\/span><span class=\"s\">NAMESPACE%-client-container<\/span>\n  <span class=\"na\">template<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">metadata<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">namespace<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">%NAMESPACE%'<\/span>\n      <span class=\"na\">labels<\/span><span class=\"pi\">:<\/span>\n        <span class=\"na\">app<\/span><span class=\"pi\">:<\/span> <span class=\"err\">%<\/span><span class=\"s\">NAMESPACE%-client<\/span>\n        <span class=\"na\">pod<\/span><span class=\"pi\">:<\/span> <span class=\"err\">%<\/span><span class=\"s\">NAMESPACE%-client-container<\/span>\n    <span class=\"na\">spec<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">containers<\/span><span class=\"pi\">:<\/span>\n        <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"err\">%<\/span><span class=\"s\">NAMESPACE%-client<\/span>\n          <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-nginx:%CLIENT_VERSION%<\/span>\n          <span class=\"na\">imagePullPolicy<\/span><span class=\"pi\">:<\/span> <span class=\"s\">IfNotPresent<\/span>\n          <span class=\"na\">ports<\/span><span class=\"pi\">:<\/span>\n            <span class=\"pi\">-<\/span> <span class=\"na\">containerPort<\/span><span class=\"pi\">:<\/span> <span class=\"err\">%<\/span><span class=\"s\">NGINX_PORT%<\/span>\n          <span class=\"na\">envFrom<\/span><span class=\"pi\">:<\/span>\n            <span class=\"pi\">-<\/span> <span class=\"na\">configMapRef<\/span><span class=\"pi\">:<\/span>\n                <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"err\">%<\/span><span class=\"s\">NAMESPACE%-config<\/span>\n            <span class=\"pi\">-<\/span> <span class=\"na\">configMapRef<\/span><span class=\"pi\">:<\/span>\n                <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"err\">%<\/span><span class=\"s\">NAMESPACE%-client-config<\/span>\n          <span class=\"na\">resources<\/span><span class=\"pi\">:<\/span>\n            <span class=\"na\">requests<\/span><span class=\"pi\">:<\/span>\n              <span class=\"na\">memory<\/span><span class=\"pi\">:<\/span> <span class=\"s\">128Mi<\/span>\n              <span class=\"na\">cpu<\/span><span class=\"pi\">:<\/span> <span class=\"s\">100m<\/span>\n            <span class=\"na\">limits<\/span><span class=\"pi\">:<\/span>\n              <span class=\"na\">memory<\/span><span class=\"pi\">:<\/span> <span class=\"s\">512Mi<\/span>\n              <span class=\"na\">cpu<\/span><span class=\"pi\">:<\/span> <span class=\"s\">300m<\/span>\n      <span class=\"na\">imagePullSecrets<\/span><span class=\"pi\">:<\/span>\n        <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">docker-regcred<\/span>\n<\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"8_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_%D8%A7%D8%B3%D8%AA%D9%82%D8%B1%D8%A7%D8%B1_CICD_%D8%A8%D8%B1%D8%A7%DB%8C_Kubernetes_%D9%88_Docker_Compose\"><\/span>\n<p>  8. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0627\u0633\u062a\u0642\u0631\u0627\u0631 CI\/CD \u0628\u0631\u0627\u06cc Kubernetes \u0648 Docker Compose<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0622\u067e\u062f\u06cc\u062a \u0628\u062e\u0634\u06cc \u0627\u0632 \u0641\u0627\u06cc\u0644 <code>.github\/workflows\/kubernetes.yml<\/code> \u0648 <code>.github\/workflows\/docker-compose.workflows.yml<\/code>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"na\">jobs<\/span><span class=\"pi\">:<\/span>\n  <span class=\"c1\"># ...<\/span>\n  <span class=\"na\">check-nginx-image<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">runs-on<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ubuntu-latest<\/span>\n    <span class=\"na\">needs<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">[<\/span><span class=\"nv\">release<\/span><span class=\"pi\">]<\/span>\n    <span class=\"na\">continue-on-error<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n    <span class=\"na\">steps<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Checkout repository<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ !contains(github.event.head_commit.message, '[skip cache]') &amp;&amp; !contains(github.event.head_commit.message, '[skip nginx cache]') }}<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/checkout@v4<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Set ENV vars<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ !contains(github.event.head_commit.message, '[skip cache]') &amp;&amp; !contains(github.event.head_commit.message, '[skip nginx cache]') }}<\/span>\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">version<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\n          <span class=\"s\">echo \"client_version=\"$(cd .\/apps\/client &amp;&amp; npm pkg get version --workspaces=false | tr -d \\\") &gt;&gt; \"$GITHUB_OUTPUT\"<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Check exists docker image<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ !contains(github.event.head_commit.message, '[skip cache]') &amp;&amp; !contains(github.event.head_commit.message, '[skip nginx cache]') }}<\/span>\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">check-exists<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\n          <span class=\"s\">export TOKEN=$(curl -u ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} https:\/\/${{ env.REGISTRY }}\/token\\?scope\\=\"repository:${{ env.NGINX_IMAGE_NAME}}:pull\" | jq -r .token)<\/span>\n          <span class=\"s\">curl --head --fail -H \"Authorization: Bearer $TOKEN\" https:\/\/${{ env.REGISTRY }}\/v2\/${{ env.NGINX_IMAGE_NAME}}\/manifests\/${{ steps.version.outputs.client_version }}<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Store result of check exists docker image<\/span>\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">store-check-exists<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ !contains(github.event.head_commit.message, '[skip cache]') &amp;&amp; !contains(github.event.head_commit.message, '[skip nginx cache]') &amp;&amp; !contains(needs.check-exists.outputs.result, 'HTTP\/2 404') }}<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\n          <span class=\"s\">echo \"conclusion=success\" &gt;&gt; \"$GITHUB_OUTPUT\"<\/span>\n    <span class=\"na\">outputs<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">result<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ steps.store-check-exists.outputs.conclusion }}<\/span>\n  <span class=\"c1\"># ...<\/span>\n  <span class=\"na\">build-and-push-nginx-image<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">runs-on<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ubuntu-latest<\/span>\n    <span class=\"na\">needs<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">[<\/span><span class=\"nv\">build-and-push-builder-image<\/span><span class=\"pi\">,<\/span> <span class=\"nv\">check-nginx-image<\/span><span class=\"pi\">]<\/span>\n    <span class=\"na\">permissions<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">contents<\/span><span class=\"pi\">:<\/span> <span class=\"s\">read<\/span>\n      <span class=\"na\">packages<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span>\n      <span class=\"na\">attestations<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span>\n      <span class=\"na\">id-token<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span>\n    <span class=\"na\">steps<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Checkout repository<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ needs.check-nginx-image.outputs.result != 'success' || contains(github.event.head_commit.message, '[skip cache]') || contains(github.event.head_commit.message, '[skip nginx cache]') }}<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/checkout@v4<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Set ENV vars<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ needs.check-nginx-image.outputs.result != 'success' || contains(github.event.head_commit.message, '[skip cache]') || contains(github.event.head_commit.message, '[skip nginx cache]') }}<\/span>\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">version<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\n          <span class=\"s\">echo \"root_version=\"$(npm pkg get version --workspaces=false | tr -d \\\") &gt;&gt; \"$GITHUB_OUTPUT\"<\/span>\n          <span class=\"s\">echo \"client_version=\"$(cd .\/apps\/client &amp;&amp; npm pkg get version --workspaces=false | tr -d \\\") &gt;&gt; \"$GITHUB_OUTPUT\"<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Log in to the Container registry<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ needs.check-nginx-image.outputs.result != 'success' || contains(github.event.head_commit.message, '[skip cache]') || contains(github.event.head_commit.message, '[skip nginx cache]') }}<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">docker\/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1<\/span>\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">registry<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ env.REGISTRY }}<\/span>\n          <span class=\"na\">username<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.actor }}<\/span>\n          <span class=\"na\">password<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ secrets.GITHUB_TOKEN }}<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Generate and build production code<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ needs.check-nginx-image.outputs.result != 'success' || contains(github.event.head_commit.message, '[skip cache]') || contains(github.event.head_commit.message, '[skip nginx cache]') }}<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\n          <span class=\"s\">mkdir -p dist<\/span>\n          <span class=\"s\">docker run -v .\/dist:\/usr\/src\/app\/dist -v .\/apps:\/usr\/src\/app\/apps -v .\/libs:\/usr\/src\/app\/libs ${{ env.REGISTRY}}\/${{ env.BUILDER_IMAGE_NAME}}:${{ steps.version.outputs.root_version }}<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Build and push Docker image<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ needs.check-nginx-image.outputs.result != 'success' || contains(github.event.head_commit.message, '[skip cache]') || contains(github.event.head_commit.message, '[skip nginx cache]') }}<\/span>\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">push<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">docker\/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4<\/span>\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">context<\/span><span class=\"pi\">:<\/span> <span class=\"s\">.<\/span>\n          <span class=\"na\">push<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n          <span class=\"na\">file<\/span><span class=\"pi\">:<\/span> <span class=\"s\">.\/.docker\/nginx.Dockerfile<\/span>\n          <span class=\"na\">tags<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ env.REGISTRY}}\/${{ env.NGINX_IMAGE_NAME}}:${{ steps.version.outputs.client_version }},${{ env.REGISTRY}}\/${{ env.NGINX_IMAGE_NAME}}:latest<\/span>\n          <span class=\"na\">cache-from<\/span><span class=\"pi\">:<\/span> <span class=\"s\">type=registry,ref=${{ env.REGISTRY}}\/${{ env.NGINX_IMAGE_NAME}}:${{ steps.version.outputs.client_version }}<\/span>\n          <span class=\"na\">cache-to<\/span><span class=\"pi\">:<\/span> <span class=\"s\">type=inline<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Generate artifact attestation<\/span>\n        <span class=\"na\">continue-on-error<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ needs.check-nginx-image.outputs.result != 'success' || contains(github.event.head_commit.message, '[skip cache]') || contains(github.event.head_commit.message, '[skip nginx cache]') }}<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/attest-build-provenance@v1<\/span>\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">subject-name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ env.REGISTRY }}\/${{ env.NGINX_IMAGE_NAME}}<\/span>\n          <span class=\"na\">subject-digest<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ steps.push.outputs.digest }}<\/span>\n          <span class=\"na\">push-to-registry<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n<\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"9_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D8%AC%D9%85%D8%B9_%D8%A2%D9%88%D8%B1%DB%8C_%DA%A9%D9%86%D9%86%D8%AF%D9%87_%D8%AA%D8%B5%D9%88%DB%8C%D8%B1_%D9%85%D8%AD%D9%84%DB%8C_Docker\"><\/span>\n<p>  9. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u062c\u0645\u0639 \u0622\u0648\u0631\u06cc \u06a9\u0646\u0646\u062f\u0647 \u062a\u0635\u0648\u06cc\u0631 \u0645\u062d\u0644\u06cc Docker<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0641\u0627\u06cc\u0644 <code>.docker\/build-images.sh<\/code>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"c\">#!\/bin\/bash<\/span>\n<span class=\"nb\">set<\/span> <span class=\"nt\">-e<\/span>\n\n<span class=\"c\"># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<\/span>\n<span class=\"nb\">export <\/span><span class=\"nv\">IMG<\/span><span class=\"o\">=<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span>\/<span class=\"k\">${<\/span><span class=\"nv\">BUILDER_IMAGE_NAME<\/span><span class=\"k\">}<\/span>:<span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">[<\/span> <span class=\"nt\">-n<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">$(<\/span>docker images <span class=\"nt\">-q<\/span> <span class=\"nv\">$IMG<\/span><span class=\"si\">)<\/span><span class=\"s2\">\"<\/span> <span class=\"o\">]<\/span> <span class=\"o\">||<\/span> docker build <span class=\"nt\">--network<\/span> host <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">BUILDER_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:<\/span><span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">BUILDER_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:latest\"<\/span> <span class=\"nt\">-f<\/span> .\/.docker\/builder.Dockerfile <span class=\"nb\">.<\/span> <span class=\"nt\">--progress<\/span><span class=\"o\">=<\/span>plain\n\n<span class=\"c\"># We build all applications<\/span>\ndocker run <span class=\"nt\">--network<\/span> host <span class=\"nt\">-v<\/span> .\/dist:\/usr\/src\/app\/dist <span class=\"nt\">-v<\/span> .\/apps:\/usr\/src\/app\/apps <span class=\"nt\">-v<\/span> .\/libs:\/usr\/src\/app\/libs <span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span>\/<span class=\"k\">${<\/span><span class=\"nv\">BUILDER_IMAGE_NAME<\/span><span class=\"k\">}<\/span>:<span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span>\n\n<span class=\"c\"># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<\/span>\n<span class=\"nb\">export <\/span><span class=\"nv\">IMG<\/span><span class=\"o\">=<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span>\/<span class=\"k\">${<\/span><span class=\"nv\">BASE_SERVER_IMAGE_NAME<\/span><span class=\"k\">}<\/span>:<span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">[<\/span> <span class=\"nt\">-n<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">$(<\/span>docker images <span class=\"nt\">-q<\/span> <span class=\"nv\">$IMG<\/span><span class=\"si\">)<\/span><span class=\"s2\">\"<\/span> <span class=\"o\">]<\/span> <span class=\"o\">||<\/span> docker build <span class=\"nt\">--network<\/span> host <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">BASE_SERVER_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:<\/span><span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">BASE_SERVER_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:latest\"<\/span> <span class=\"nt\">-f<\/span> .\/.docker\/base-server.Dockerfile <span class=\"nb\">.<\/span> <span class=\"nt\">--progress<\/span><span class=\"o\">=<\/span>plain\n\n<span class=\"c\"># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<\/span>\n<span class=\"nb\">export <\/span><span class=\"nv\">IMG<\/span><span class=\"o\">=<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span>\/<span class=\"k\">${<\/span><span class=\"nv\">SERVER_IMAGE_NAME<\/span><span class=\"k\">}<\/span>:<span class=\"k\">${<\/span><span class=\"nv\">SERVER_VERSION<\/span><span class=\"k\">}<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">[<\/span> <span class=\"nt\">-n<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">$(<\/span>docker images <span class=\"nt\">-q<\/span> <span class=\"nv\">$IMG<\/span><span class=\"si\">)<\/span><span class=\"s2\">\"<\/span> <span class=\"o\">]<\/span> <span class=\"o\">||<\/span> docker build <span class=\"nt\">--network<\/span> host <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">SERVER_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:<\/span><span class=\"k\">${<\/span><span class=\"nv\">SERVER_VERSION<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">SERVER_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:latest\"<\/span> <span class=\"nt\">-f<\/span> .\/.docker\/server.Dockerfile <span class=\"nb\">.<\/span> <span class=\"nt\">--progress<\/span><span class=\"o\">=<\/span>plain <span class=\"nt\">--build-arg<\/span><span class=\"o\">=<\/span><span class=\"se\">\\\"<\/span><span class=\"nv\">BASE_SERVER_IMAGE_TAG<\/span><span class=\"o\">=<\/span><span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span><span class=\"se\">\\\"<\/span>\n\n<span class=\"c\"># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<\/span>\n<span class=\"nb\">export <\/span><span class=\"nv\">IMG<\/span><span class=\"o\">=<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span>\/<span class=\"k\">${<\/span><span class=\"nv\">MIGRATIONS_IMAGE_NAME<\/span><span class=\"k\">}<\/span>:<span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">[<\/span> <span class=\"nt\">-n<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">$(<\/span>docker images <span class=\"nt\">-q<\/span> <span class=\"nv\">$IMG<\/span><span class=\"si\">)<\/span><span class=\"s2\">\"<\/span> <span class=\"o\">]<\/span> <span class=\"o\">||<\/span> docker build <span class=\"nt\">--network<\/span> host <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">MIGRATIONS_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:<\/span><span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">MIGRATIONS_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:latest\"<\/span> <span class=\"nt\">-f<\/span> .\/.docker\/migrations.Dockerfile <span class=\"nb\">.<\/span> <span class=\"nt\">--progress<\/span><span class=\"o\">=<\/span>plain\n\n<span class=\"c\"># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<\/span>\n<span class=\"nb\">export <\/span><span class=\"nv\">IMG<\/span><span class=\"o\">=<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span>\/<span class=\"k\">${<\/span><span class=\"nv\">NGINX_IMAGE_NAME<\/span><span class=\"k\">}<\/span>:<span class=\"k\">${<\/span><span class=\"nv\">CLIENT_VERSION<\/span><span class=\"k\">}<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">[<\/span> <span class=\"nt\">-n<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">$(<\/span>docker images <span class=\"nt\">-q<\/span> <span class=\"nv\">$IMG<\/span><span class=\"si\">)<\/span><span class=\"s2\">\"<\/span> <span class=\"o\">]<\/span> <span class=\"o\">||<\/span> docker build <span class=\"nt\">--network<\/span> host <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">NGINX_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:<\/span><span class=\"k\">${<\/span><span class=\"nv\">CLIENT_VERSION<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">NGINX_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:latest\"<\/span> <span class=\"nt\">-f<\/span> .\/.docker\/nginx.Dockerfile <span class=\"nb\">.<\/span> <span class=\"nt\">--progress<\/span><span class=\"o\">=<\/span>plain\n\n<span class=\"c\"># We check the existence of a local image with the specified tag, if it does not exist, we start building the image<\/span>\n<span class=\"nb\">export <\/span><span class=\"nv\">IMG<\/span><span class=\"o\">=<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span>\/<span class=\"k\">${<\/span><span class=\"nv\">E2E_TESTS_IMAGE_NAME<\/span><span class=\"k\">}<\/span>:<span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">[<\/span> <span class=\"nt\">-n<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">$(<\/span>docker images <span class=\"nt\">-q<\/span> <span class=\"nv\">$IMG<\/span><span class=\"si\">)<\/span><span class=\"s2\">\"<\/span> <span class=\"o\">]<\/span> <span class=\"o\">||<\/span> docker build <span class=\"nt\">--network<\/span> host <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">E2E_TESTS_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:<\/span><span class=\"k\">${<\/span><span class=\"nv\">ROOT_VERSION<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">-t<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">REGISTRY<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">E2E_TESTS_IMAGE_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">:latest\"<\/span> <span class=\"nt\">-f<\/span> .\/.docker\/e2e-tests.Dockerfile <span class=\"nb\">.<\/span> <span class=\"nt\">--progress<\/span><span class=\"o\">=<\/span>plain\n\n<\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"10_%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%D9%85%D8%AD%D9%84%DB%8C_%D8%AD%D8%A7%D9%84%D8%AA_%E2%80%9CDocker_Compose%E2%80%9D\"><\/span>\n<p>  10. \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0628\u0631\u0627\u06cc \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0645\u062d\u0644\u06cc \u062d\u0627\u0644\u062a &#8220;Docker Compose&#8221;.<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0641\u0627\u06cc\u0644 <code>.docker\/docker-compose-full.yml<\/code>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"na\">version<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">3'<\/span>\n<span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">nestjs-mod-fullstack-network<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">driver<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">bridge'<\/span>\n<span class=\"na\">services<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">nestjs-mod-fullstack-postgre-sql<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">bitnami\/postgresql:15.5.0'<\/span>\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-postgre-sql'<\/span>\n    <span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-network'<\/span>\n    <span class=\"na\">healthcheck<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">test<\/span><span class=\"pi\">:<\/span>\n        <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">CMD-SHELL'<\/span>\n        <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">pg_isready<\/span><span class=\"nv\"> <\/span><span class=\"s\">-U<\/span><span class=\"nv\"> <\/span><span class=\"s\">postgres'<\/span>\n      <span class=\"na\">interval<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">5s'<\/span>\n      <span class=\"na\">timeout<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">5s'<\/span>\n      <span class=\"na\">retries<\/span><span class=\"pi\">:<\/span> <span class=\"m\">5<\/span>\n    <span class=\"na\">tty<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n    <span class=\"na\">restart<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">always'<\/span>\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">POSTGRESQL_USERNAME<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${SERVER_POSTGRE_SQL_POSTGRESQL_USERNAME}'<\/span>\n      <span class=\"na\">POSTGRESQL_PASSWORD<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${SERVER_POSTGRE_SQL_POSTGRESQL_PASSWORD}'<\/span>\n      <span class=\"na\">POSTGRESQL_DATABASE<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${SERVER_POSTGRE_SQL_POSTGRESQL_DATABASE}'<\/span>\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-postgre-sql-volume:\/bitnami\/postgresql'<\/span>\n  <span class=\"na\">nestjs-mod-fullstack-postgre-sql-migrations<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-migrations:${ROOT_VERSION}'<\/span>\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-postgre-sql-migrations'<\/span>\n    <span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-network'<\/span>\n    <span class=\"na\">tty<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">NX_SKIP_NX_CACHE<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">true'<\/span>\n      <span class=\"na\">SERVER_ROOT_DATABASE_URL<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${SERVER_ROOT_DATABASE_URL}'<\/span>\n      <span class=\"na\">SERVER_APP_DATABASE_URL<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${SERVER_APP_DATABASE_URL}'<\/span>\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">nestjs-mod-fullstack-postgre-sql<\/span><span class=\"pi\">:<\/span>\n        <span class=\"na\">condition<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">service_healthy'<\/span>\n    <span class=\"na\">working_dir<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">\/usr\/src\/app'<\/span>\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">.\/..\/apps:\/usr\/src\/app\/apps'<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">.\/..\/libs:\/usr\/src\/app\/libs'<\/span>\n  <span class=\"na\">nestjs-mod-fullstack-server<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-server:${SERVER_VERSION}'<\/span>\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-server'<\/span>\n    <span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-network'<\/span>\n    <span class=\"na\">healthcheck<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">test<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">[<\/span><span class=\"s1\">'<\/span><span class=\"s\">CMD-SHELL'<\/span><span class=\"pi\">,<\/span> <span class=\"s1\">'<\/span><span class=\"s\">npx<\/span><span class=\"nv\"> <\/span><span class=\"s\">-y<\/span><span class=\"nv\"> <\/span><span class=\"s\">wait-on<\/span><span class=\"nv\"> <\/span><span class=\"s\">--timeout=<\/span><span class=\"nv\"> <\/span><span class=\"s\">--interval=1000<\/span><span class=\"nv\"> <\/span><span class=\"s\">--window<\/span><span class=\"nv\"> <\/span><span class=\"s\">--verbose<\/span><span class=\"nv\"> <\/span><span class=\"s\">--log<\/span><span class=\"nv\"> <\/span><span class=\"s\">http:\/\/localhost:${SERVER_PORT}\/api\/health'<\/span><span class=\"pi\">]<\/span>\n      <span class=\"na\">interval<\/span><span class=\"pi\">:<\/span> <span class=\"s\">30s<\/span>\n      <span class=\"na\">timeout<\/span><span class=\"pi\">:<\/span> <span class=\"s\">10s<\/span>\n      <span class=\"na\">retries<\/span><span class=\"pi\">:<\/span> <span class=\"m\">10<\/span>\n    <span class=\"na\">tty<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">SERVER_APP_DATABASE_URL<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${SERVER_APP_DATABASE_URL}'<\/span>\n      <span class=\"na\">SERVER_PORT<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${SERVER_PORT}'<\/span>\n    <span class=\"na\">restart<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">always'<\/span>\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">nestjs-mod-fullstack-postgre-sql<\/span><span class=\"pi\">:<\/span>\n        <span class=\"na\">condition<\/span><span class=\"pi\">:<\/span> <span class=\"s\">service_healthy<\/span>\n      <span class=\"na\">nestjs-mod-fullstack-postgre-sql-migrations<\/span><span class=\"pi\">:<\/span>\n        <span class=\"na\">condition<\/span><span class=\"pi\">:<\/span> <span class=\"s\">service_completed_successfully<\/span>\n  <span class=\"na\">nestjs-mod-fullstack-nginx<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-nginx:${CLIENT_VERSION}'<\/span>\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-nginx'<\/span>\n    <span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-network'<\/span>\n    <span class=\"na\">healthcheck<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">test<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">[<\/span><span class=\"s1\">'<\/span><span class=\"s\">CMD-SHELL'<\/span><span class=\"pi\">,<\/span> <span class=\"s1\">'<\/span><span class=\"s\">curl<\/span><span class=\"nv\"> <\/span><span class=\"s\">-so<\/span><span class=\"nv\"> <\/span><span class=\"s\">\/dev\/null<\/span><span class=\"nv\"> <\/span><span class=\"s\">http:\/\/localhost:${NGINX_PORT}<\/span><span class=\"nv\"> <\/span><span class=\"s\">||<\/span><span class=\"nv\"> <\/span><span class=\"s\">exit<\/span><span class=\"nv\"> <\/span><span class=\"s\">1'<\/span><span class=\"pi\">]<\/span>\n      <span class=\"na\">interval<\/span><span class=\"pi\">:<\/span> <span class=\"s\">30s<\/span>\n      <span class=\"na\">timeout<\/span><span class=\"pi\">:<\/span> <span class=\"s\">10s<\/span>\n      <span class=\"na\">retries<\/span><span class=\"pi\">:<\/span> <span class=\"m\">10<\/span>\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">SERVER_PORT<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${SERVER_PORT}'<\/span>\n      <span class=\"na\">NGINX_PORT<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${NGINX_PORT}'<\/span>\n    <span class=\"na\">restart<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">always'<\/span>\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">nestjs-mod-fullstack-server<\/span><span class=\"pi\">:<\/span>\n        <span class=\"na\">condition<\/span><span class=\"pi\">:<\/span> <span class=\"s\">service_healthy<\/span>\n    <span class=\"na\">ports<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${NGINX_PORT}:${NGINX_PORT}'<\/span>\n  <span class=\"na\">nestjs-mod-fullstack-e2e-tests<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">ghcr.io\/nestjs-mod\/nestjs-mod-fullstack-e2e-tests:${ROOT_VERSION}'<\/span>\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-e2e-tests'<\/span>\n    <span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-network'<\/span>\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">BASE_URL<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">http:\/\/nestjs-mod-fullstack-nginx:${NGINX_PORT}'<\/span>\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">nestjs-mod-fullstack-nginx<\/span><span class=\"pi\">:<\/span>\n        <span class=\"na\">condition<\/span><span class=\"pi\">:<\/span> <span class=\"s\">service_healthy<\/span>\n    <span class=\"na\">working_dir<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">\/usr\/src\/app'<\/span>\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">.\/..\/apps:\/usr\/src\/app\/apps'<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">.\/..\/libs:\/usr\/src\/app\/libs'<\/span>\n  <span class=\"na\">nestjs-mod-fullstack-https-portal<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s\">steveltn\/https-portal:1<\/span>\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-https-portal'<\/span>\n    <span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-network'<\/span>\n    <span class=\"na\">ports<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">80:80'<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">443:443'<\/span>\n    <span class=\"na\">links<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s\">nestjs-mod-fullstack-nginx<\/span>\n    <span class=\"na\">restart<\/span><span class=\"pi\">:<\/span> <span class=\"s\">always<\/span>\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">STAGE<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${HTTPS_PORTAL_STAGE}'<\/span>\n      <span class=\"na\">DOMAINS<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">${SERVER_DOMAIN}<\/span><span class=\"nv\"> <\/span><span class=\"s\">-&gt;<\/span><span class=\"nv\"> <\/span><span class=\"s\">http:\/\/nestjs-mod-fullstack-nginx:${NGINX_PORT}'<\/span>\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">nestjs-mod-fullstack-nginx<\/span><span class=\"pi\">:<\/span>\n        <span class=\"na\">condition<\/span><span class=\"pi\">:<\/span> <span class=\"s\">service_healthy<\/span>\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s\">nestjs-mod-fullstack-https-portal-volume:\/var\/lib\/https-portal<\/span>\n<span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">nestjs-mod-fullstack-postgre-sql-volume<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-postgre-sql-volume'<\/span>\n  <span class=\"na\">nestjs-mod-fullstack-https-portal-volume<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">nestjs-mod-fullstack-https-portal-volume'<\/span>\n<\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"11_%D8%AD%D8%A7%D9%84%D8%AA_%D9%85%D8%AD%D9%84%DB%8C_%E2%80%9CDocker_Compose%E2%80%9D_%D8%B1%D8%A7_%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%D9%85%DB%8C_%DA%A9%D9%86%DB%8C%D9%85_%D9%88_%D9%85%D9%86%D8%AA%D8%B8%D8%B1_%D8%AA%DA%A9%D9%85%DB%8C%D9%84_%D9%85%D9%88%D9%81%D9%82%DB%8C%D8%AA_%D8%A2%D9%85%DB%8C%D8%B2_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7_%D9%87%D8%B3%D8%AA%DB%8C%D9%85\"><\/span>\n<p>  11. \u062d\u0627\u0644\u062a \u0645\u062d\u0644\u06cc &#8220;Docker Compose&#8221; \u0631\u0627 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645 \u0648 \u0645\u0646\u062a\u0638\u0631 \u062a\u06a9\u0645\u06cc\u0644 \u0645\u0648\u0641\u0642\u06cc\u062a \u0622\u0645\u06cc\u0632 \u062a\u0633\u062a \u0647\u0627 \u0647\u0633\u062a\u06cc\u0645<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u0632\u06cc\u0627\u062f\u06cc \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc \u062f\u0647\u06cc\u0645 \u06cc\u0627 \u067e\u0627\u0631\u0627\u0645\u062a\u0631\u0647\u0627\u06cc devops \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc \u062f\u0647\u06cc\u0645 \u06cc\u0627 \u0648\u0627\u0628\u0633\u062a\u06af\u06cc \u0647\u0627\u06cc \u062c\u062f\u06cc\u062f \u0646\u0635\u0628 \u0645\u06cc \u06a9\u0646\u06cc\u0645\u060c \u0628\u0627\u06cc\u062f \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u0645\u0637\u0645\u0626\u0646 \u0634\u0648\u06cc\u0645 \u06a9\u0647 \u0647\u0645\u0647 \u0686\u06cc\u0632 \u062f\u0631 \u062d\u0627\u0644\u062a &#8220;Docker Compose&#8221; \u06a9\u0627\u0631 \u0645\u06cc \u06a9\u0646\u062f\u060c \u0632\u06cc\u0631\u0627 \u0641\u0631\u0622\u06cc\u0646\u062f \u0633\u0627\u062e\u062a \u062f\u0631 CI\/CD \u0645\u062d\u062f\u0648\u062f\u06cc\u062a \u0647\u0627\u06cc \u0631\u0627\u06cc\u06af\u0627\u0646 \u0631\u0627 \u062f\u0631 \u0645\u0648\u0627\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0635\u0631\u0641 \u0645\u06cc \u06a9\u0646\u062f. \u062f\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0639\u0645\u0648\u0645\u06cc\u060c \u0648 \u0647\u0645\u0686\u0646\u06cc\u0646 \u0647\u0646\u06af\u0627\u0645 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u062f\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u06a9\u0645 \u0645\u0635\u0631\u0641 \u062e\u0648\u062f\u060c \u0641\u0631\u0622\u06cc\u0646\u062f \u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0631\u0627 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0648 \u0627\u0641\u0632\u0627\u06cc\u0634 \u0645\u06cc \u062f\u0647\u062f.<\/p>\n<p>\u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0645\u062d\u0644\u06cc \u062f\u0631 \u062d\u0627\u0644\u062a &#8220;Docker Compose&#8221; \u0647\u0645\u0686\u0646\u06cc\u0646 \u0628\u0647 \u0634\u0645\u0627 \u0627\u0645\u06a9\u0627\u0646 \u0645\u06cc \u062f\u0647\u062f \u0645\u0634\u06a9\u0644\u0627\u062a\u06cc \u0631\u0627 \u06a9\u0647 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0647\u0646\u06af\u0627\u0645 \u0627\u062c\u0631\u0627 \u0627\u0632 \u0637\u0631\u06cc\u0642 Kubernetes \u0638\u0627\u0647\u0631 \u0634\u0648\u0646\u062f \u0634\u0646\u0627\u0633\u0627\u06cc\u06cc \u06a9\u0646\u06cc\u062f\u060c \u0632\u06cc\u0631\u0627 \u0645\u0648\u0646\u062a\u0627\u0698 <code>Docker<\/code> \u062a\u0635\u0627\u0648\u06cc\u0631 \u06cc\u06a9\u0633\u0627\u0646 \u0627\u0633\u062a<\/p>\n<p>\u0648\u0642\u062a\u06cc \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u0627\u062c\u0631\u0627 \u0645\u06cc\u200c\u0634\u0648\u062f\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u0645 \u0622\u0646 \u0631\u0627 \u062f\u0627\u0646\u0644\u0648\u062f \u0648 \u0648\u0635\u0644 \u06a9\u0646\u06cc\u0645 <code>Docker<\/code> \u062a\u0635\u0627\u0648\u06cc\u0631\u06cc \u06a9\u0647 \u062f\u0631 Kubernetes \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0634\u062f\u0647\u200c\u0627\u0646\u062f\u060c \u0628\u0647 \u06cc\u0627\u0641\u062a\u0646 \u0627\u0634\u06a9\u0627\u0644\u0627\u062a\u06cc \u06a9\u0645\u06a9 \u0645\u06cc\u200c\u06a9\u0646\u062f \u06a9\u0647 \u062f\u0631 \u0645\u0627\u0634\u06cc\u0646\u200c\u0647\u0627\u06cc \u0645\u0627 \u0648 \u062f\u0631 \u0645\u0648\u0646\u062a\u0627\u0698 \u0645\u062d\u0644\u06cc \u0645\u0627 \u062a\u06a9\u0631\u0627\u0631 \u0646\u0645\u06cc\u200c\u0634\u0648\u0646\u062f. <code>Docker<\/code> \u062a\u0635\u0627\u0648\u06cc\u0631<\/p>\n<p><em>\u062f\u0633\u062a\u0648\u0631\u0627\u062a<\/em>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npm run docker-compose-full:prod:start\ndocker logs nestjs-mod-fullstack-e2e-tests\n<\/code><\/pre>\n<\/div>\n<p><em>\u062e\u0631\u0648\u062c\u06cc \u0647\u0627\u06cc \u06a9\u0646\u0633\u0648\u0644<\/em>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>docker logs nestjs-mod-fullstack-e2e-tests\n\n<span class=\"o\">&gt;<\/span> @nestjs-mod-fullstack\/source@0.0.0 <span class=\"nb\">test<\/span>:e2e\n<span class=\"o\">&gt;<\/span> .\/node_modules\/.bin\/nx run-many <span class=\"nt\">--exclude<\/span><span class=\"o\">=<\/span>@nestjs-mod-fullstack\/source <span class=\"nt\">--all<\/span> <span class=\"nt\">-t<\/span><span class=\"o\">=<\/span>e2e <span class=\"nt\">--skip-nx-cache<\/span><span class=\"o\">=<\/span><span class=\"nb\">true<\/span> <span class=\"nt\">--output-style<\/span><span class=\"o\">=<\/span>stream-without-prefixes\n\nNX  Falling back to ts-node <span class=\"k\">for <\/span><span class=\"nb\">local <\/span>typescript execution. This may be a little slower.\n - To fix this, ensure @swc-node\/register and @swc\/core have been installed\n\n NX   Running target e2e <span class=\"k\">for <\/span>2 projects:\n\n- client-e2e\n- server-e2e\n\n\n\n<span class=\"o\">&gt;<\/span> nx run client-e2e:e2e\n\n<span class=\"o\">&gt;<\/span> playwright <span class=\"nb\">test\n\n\n<\/span>Running 6 tests using 3 workers\n  6 passed <span class=\"o\">(<\/span>4.9s<span class=\"o\">)<\/span>\n\nTo open last HTML report run:\n\n  npx playwright show-report ..\/..\/dist\/.playwright\/apps\/client-e2e\/playwright-report\n\n\n<span class=\"o\">&gt;<\/span> nx run server-e2e:e2e\n\nSetting up...\n PASS   server-e2e  apps\/server-e2e\/src\/server\/server.spec.ts\n  GET \/api\n    \u2713 should <span class=\"k\">return <\/span>a message <span class=\"o\">(<\/span>32 ms<span class=\"o\">)<\/span>\n    \u2713 should create and <span class=\"k\">return <\/span>a demo object <span class=\"o\">(<\/span>38 ms<span class=\"o\">)<\/span>\n    \u2713 should get demo object by <span class=\"nb\">id<\/span> <span class=\"o\">(<\/span>9 ms<span class=\"o\">)<\/span>\n    \u2713 should get all demo object <span class=\"o\">(<\/span>7 ms<span class=\"o\">)<\/span>\n    \u2713 should delete demo object by <span class=\"nb\">id<\/span> <span class=\"o\">(<\/span>8 ms<span class=\"o\">)<\/span>\n    \u2713 should get all demo object <span class=\"o\">(<\/span>6 ms<span class=\"o\">)<\/span>\nTest Suites: 1 passed, 1 total\nTests:       6 passed, 6 total\nSnapshots:   0 total\nTime:        0.789 s\nRan all <span class=\"nb\">test <\/span>suites.\nTearing down...\n\n\n\n NX   Successfully ran target e2e <span class=\"k\">for <\/span>2 projects\n<\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"12_%D8%AC%D8%A7%DB%8C%DA%AF%D8%B2%DB%8C%D9%86_%DA%A9%D8%B1%D8%AF%D9%86_%DA%86%DA%A9_%D8%A8%D8%B1%D8%A7%DB%8C_%D9%86%D8%B4%D8%A7%D9%86%DA%AF%D8%B1_%D8%A7%D9%86%D8%AA%D8%B4%D8%A7%D8%B1_%D8%AF%D8%B1_%D9%86%D8%B8%D8%B1_commit_%D8%A8%D8%A7_%DB%8C%DA%A9_%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C_%D8%A8%D8%B1%D8%A7%DB%8C_%D9%86%D8%B4%D8%A7%D9%86%DA%AF%D8%B1_%D8%A7%D9%86%D8%AA%D8%B4%D8%A7%D8%B1_%D9%BE%D8%B1%D8%B4\"><\/span>\n<p>  12. \u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u06a9\u0631\u062f\u0646 \u0686\u06a9 \u0628\u0631\u0627\u06cc \u0646\u0634\u0627\u0646\u06af\u0631 \u0627\u0646\u062a\u0634\u0627\u0631 \u062f\u0631 \u0646\u0638\u0631 commit \u0628\u0627 \u06cc\u06a9 \u0628\u0631\u0631\u0633\u06cc \u0628\u0631\u0627\u06cc \u0646\u0634\u0627\u0646\u06af\u0631 \u0627\u0646\u062a\u0634\u0627\u0631 \u067e\u0631\u0634<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062f\u0631 \u067e\u0633\u062a \u0642\u0628\u0644\u06cc \u0646\u0634\u0627\u0646\u06af\u0631 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0645 <code>[release]<\/code> \u0628\u0627 \u062a\u0648\u062c\u0647 \u0628\u0647 \u0627\u06cc\u0646\u06a9\u0647 \u0645\u0627 \u062f\u0631 \u0645\u0648\u0631\u062f \u0646\u06cc\u0627\u0632 \u0628\u0647 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u06cc\u06a9 \u0646\u0633\u062e\u0647 \u062a\u0635\u0645\u06cc\u0645 \u06af\u0631\u0641\u062a\u06cc\u0645\u060c \u0628\u06cc\u0634\u062a\u0631 \u0634\u0628\u06cc\u0647 \u06cc\u06a9 \u0646\u0645\u0648\u0646\u0647 \u0628\u0648\u062f\u060c \u062f\u0631 \u0648\u0627\u0642\u0639 \u0622\u0646\u0647\u0627 \u0647\u0645\u06cc\u0634\u0647 \u0646\u0648\u0634\u062a\u0646 \u0627\u06cc\u0646 \u0646\u0634\u0627\u0646\u06af\u0631 \u0631\u0627 \u0641\u0631\u0627\u0645\u0648\u0634 \u0645\u06cc \u06a9\u0646\u0646\u062f \u0648 \u0645\u062c\u0628\u0648\u0631\u0646\u062f \u06cc\u06a9 \u062a\u0639\u0647\u062f \u063a\u06cc\u0631 \u0636\u0631\u0648\u0631\u06cc \u063a\u06cc\u0631 \u0645\u0647\u0645 \u0631\u0627 \u0628\u0631\u0627\u06cc \u0627\u062c\u0628\u0627\u0631 \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 \u0646\u0633\u062e\u0647 \u0627\u0646\u062c\u0627\u0645 \u062f\u0647\u0646\u062f.<\/p>\n<p>\u0628\u0631\u0627\u06cc \u0627\u06cc\u0646\u06a9\u0647 \u0646\u0633\u062e\u0647 \u0647\u0645\u06cc\u0634\u0647 \u0634\u0631\u0648\u0639 \u0628\u0647 \u06a9\u0627\u0631 \u06a9\u0646\u062f\u060c \u0646\u0634\u0627\u0646\u06af\u0631 \u0631\u0627 \u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u06a9\u0646\u06cc\u062f <code>[release]<\/code> \u0628\u0627 <code>[skip release]<\/code> \u0648 \u0645\u0646\u0637\u0642 \u06a9\u0627\u0631 \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0647\u06cc\u062f\u060c \u062d\u0627\u0644\u0627 \u062f\u0631 \u0635\u0648\u0631\u062a \u0631\u0633\u06cc\u062f\u0646 \u0628\u0647 \u0646\u0634\u0627\u0646\u06af\u0631 \u0645\u0634\u062e\u0635 \u0634\u062f\u0647\u060c \u0627\u0632 \u0645\u0631\u062d\u0644\u0647 \u0627\u06cc\u062c\u0627\u062f \u0627\u0646\u062a\u0634\u0627\u0631 \u0645\u06cc \u06af\u0630\u0631\u06cc\u0645.<\/p>\n<p>\u062f\u0631 \u062d\u0627\u0644 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0641\u0627\u06cc\u0644 <code>.github\/workflows\/kubernetes.yml<\/code>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">Kubernetes'<\/span>\n\n<span class=\"na\">on<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">push<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">branches<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">[<\/span><span class=\"s1\">'<\/span><span class=\"s\">master'<\/span><span class=\"pi\">]<\/span>\n<span class=\"na\">env<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">REGISTRY<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ghcr.io<\/span>\n  <span class=\"na\">BASE_SERVER_IMAGE_NAME<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.repository }}-base-server<\/span>\n  <span class=\"na\">BUILDER_IMAGE_NAME<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.repository }}-builder<\/span>\n  <span class=\"na\">MIGRATIONS_IMAGE_NAME<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.repository }}-migrations<\/span>\n  <span class=\"na\">SERVER_IMAGE_NAME<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.repository }}-server<\/span>\n  <span class=\"na\">NGINX_IMAGE_NAME<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.repository }}-nginx<\/span>\n  <span class=\"na\">E2E_TESTS_IMAGE_NAME<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.repository }}-e2e-tests<\/span>\n  <span class=\"na\">COMPOSE_INTERACTIVE_NO_CLI<\/span><span class=\"pi\">:<\/span> <span class=\"m\">1<\/span>\n  <span class=\"na\">NX_DAEMON<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">false<\/span>\n  <span class=\"na\">NX_PARALLEL<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">false<\/span>\n  <span class=\"na\">NX_SKIP_NX_CACHE<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n  <span class=\"na\">DISABLE_SERVE_STATIC<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n<span class=\"na\">jobs<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">release<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">runs-on<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ubuntu-latest<\/span>\n    <span class=\"na\">permissions<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">contents<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span> <span class=\"c1\"># to be able to publish a GitHub release<\/span>\n      <span class=\"na\">issues<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span> <span class=\"c1\"># to be able to comment on released issues<\/span>\n      <span class=\"na\">pull-requests<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span> <span class=\"c1\"># to be able to comment on released pull requests<\/span>\n      <span class=\"na\">id-token<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span> <span class=\"c1\"># to enable use of OIDC for npm provenance<\/span>\n    <span class=\"na\">steps<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/checkout@v4<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ !contains(github.event.head_commit.message, '[skip release]') }}<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">npm install --prefer-offline --no-audit --progress=false<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ !contains(github.event.head_commit.message, '[skip release]') }}<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">npm run nx -- run-many --target=semantic-release --all --parallel=false<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ !contains(github.event.head_commit.message, '[skip release]') }}<\/span>\n        <span class=\"na\">env<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">GITHUB_TOKEN<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ secrets.GITHUB_TOKEN }}<\/span>\n<span class=\"c1\"># ...<\/span>\n<\/code><\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"13_%D8%A7%D9%81%D8%B2%D9%88%D8%AF%D9%86_%D8%B3%D8%AE%D8%AA%DA%AF%DB%8C%D8%B1%DB%8C_%D8%A8%D9%87_%DA%A9%D8%AF\"><\/span>\n<p>  13. \u0627\u0641\u0632\u0648\u062f\u0646 \u0633\u062e\u062a\u06af\u06cc\u0631\u06cc \u0628\u0647 \u06a9\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0639\u0644\u0627\u0648\u0647 \u0628\u0631 <code>lint-staged<\/code> \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0628\u0631\u0627\u06cc \u0622\u0648\u0631\u062f\u0646 \u06a9\u062f \u0628\u0647 \u06cc\u06a9 \u0633\u0628\u06a9 \u0645\u0634\u062a\u0631\u06a9\u060c \u0647\u0645\u0686\u0646\u06cc\u0646 \u0644\u0627\u0632\u0645 \u0627\u0633\u062a \u0645\u0634\u062a\u0631\u06a9 \u0628\u0627\u0634\u062f <code>eslint<\/code> \u0648 <code>typescript-CompilerOptions<\/code> \u067e\u0627\u0631\u0627\u0645\u062a\u0631\u0647\u0627 \u0628\u0627 \u0642\u0648\u0627\u0646\u06cc\u0646 \u0633\u062e\u062a\u06af\u06cc\u0631\u06cc \u06a9\u062f \u0627\u0636\u0627\u0641\u06cc.<\/p>\n<p>\u0645\u0646 \u0645\u0639\u0645\u0648\u0644\u0627\u064b \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0631\u0627 \u0644\u0645\u0633 \u0646\u0645\u06cc \u06a9\u0646\u0645 <code>eslint<\/code> \u0648 <code>prettier<\/code> \u062a\u0646\u0638\u06cc\u0645\u0627\u062a\u060c \u0641\u0642\u0637 \u06a9\u0645\u06cc \u0633\u062e\u062a\u06af\u06cc\u0631\u06cc \u0631\u0627 \u0628\u0647 \u0631\u06cc\u0634\u0647 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f <code>Typescript<\/code> \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc<\/p>\n<p>\u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u0642\u0648\u0627\u0646\u06cc\u0646 \u0627\u0636\u0627\u0641\u06cc \u0628\u0647 <code>tsconfig.base.json<\/code>\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight json\"><code><span class=\"p\">{<\/span><span class=\"w\">\n  <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"compilerOptions\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n    <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"allowSyntheticDefaultImports\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"strictNullChecks\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"noImplicitOverride\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"strictPropertyInitialization\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"noImplicitReturns\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"noFallthroughCasesInSwitch\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"esModuleInterop\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><span class=\"w\">\n    <\/span><span class=\"nl\">\"noImplicitAny\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">false<\/span><span class=\"w\">\n    <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n  <\/span><span class=\"p\">}<\/span><span class=\"w\">\n  <\/span><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">...<\/span><span class=\"w\">\n<\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><\/code><\/pre>\n<\/div>\n<p>\u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f <code>npm run manual:prepare<\/code> \u0648 \u0647\u0631 \u0686\u06cc\u0632\u06cc \u06a9\u0647 \u062e\u0631\u0627\u0628 \u0627\u0633\u062a \u0631\u0627 \u0627\u0635\u0644\u0627\u062d \u06a9\u0646\u06cc\u062f \u0648 \u062f\u0648\u0628\u0627\u0631\u0647 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u06a9\u0646\u06cc\u062f \u062a\u0627 \u062a\u0645\u0627\u0645 \u062e\u0637\u0627\u0647\u0627 \u0631\u0627 \u0628\u0631\u0637\u0631\u0641 \u06a9\u0646\u06cc\u0645.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"14_%DA%A9%D8%AF_%D8%B1%D8%A7_%D9%85%D8%AA%D8%B9%D9%87%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF_%D9%88_%D9%85%D9%86%D8%AA%D8%B8%D8%B1_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%D9%85%D9%88%D9%81%D9%82%DB%8C%D8%AA_%D8%A2%D9%85%DB%8C%D8%B2_%D9%86%D8%B3%D8%AE%D9%87_%D9%87%D8%A7_%D9%88_%DA%AF%D8%B0%D8%B1%D8%A7%D9%86%D8%AF%D9%86_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7_%D8%A8%D8%A7%D8%B4%DB%8C%D8%AF\"><\/span>\n<p>  14. \u06a9\u062f \u0631\u0627 \u0645\u062a\u0639\u0647\u062f \u06a9\u0646\u06cc\u062f \u0648 \u0645\u0646\u062a\u0638\u0631 \u0627\u06cc\u062c\u0627\u062f \u0645\u0648\u0641\u0642\u06cc\u062a \u0622\u0645\u06cc\u0632 \u0646\u0633\u062e\u0647 \u0647\u0627 \u0648 \u06af\u0630\u0631\u0627\u0646\u062f\u0646 \u062a\u0633\u062a \u0647\u0627 \u0628\u0627\u0634\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0646\u062a\u06cc\u062c\u0647 \u0641\u0639\u0644\u06cc \u0639\u0645\u0644\u06cc\u0627\u062a CI\/CD: https:\/\/github.com\/nestjs-mod\/nestjs-mod-fullstack\/actions\/runs\/10904254598<br \/>\n\u0633\u0627\u06cc\u062a \u0641\u0639\u0644\u06cc: https:\/\/fullstack.nestjs-mod.com<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D9%86%D8%AA%DB%8C%D8%AC%D9%87_%DA%AF%DB%8C%D8%B1%DB%8C\"><\/span>\n<p>  \u0646\u062a\u06cc\u062c\u0647 \u06af\u06cc\u0631\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06af\u0631 \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u062f\u06cc\u06af\u0631\u06cc \u062f\u0631 \u067e\u0631\u0648\u0698\u0647 \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f \u06a9\u0647 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0628\u0633\u062a\u0647 \u0628\u0647 \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0645\u062d\u06cc\u0637 \u062a\u0648\u0633\u0639\u0647 \u062a\u063a\u06cc\u06cc\u0631 \u06a9\u0646\u062f\u060c \u0627\u06cc\u0646 \u0641\u0627\u06cc\u0644 \u0647\u0627 \u0646\u06cc\u0632 \u0628\u0627\u06cc\u062f \u062f\u0631 <code>lint-staged<\/code> \u0642\u0648\u0627\u0646\u06cc\u0646.<\/p>\n<p>\u0633\u062e\u062a\u06cc \u0631\u0627 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646 \u062d\u062a\u06cc \u0642\u0648\u06cc\u200c\u062a\u0631 \u06a9\u0631\u062f\u060c \u0648 \u0647\u0645\u0686\u0646\u06cc\u0646 <code>eslint<\/code> \u0642\u0648\u0627\u0646\u06cc\u0646\u060c \u0627\u0645\u0627 \u0647\u0631 \u0628\u0627\u0631 \u0628\u0627\u06cc\u062f \u0632\u0645\u0627\u0646 \u0627\u062c\u0631\u0627 \u0631\u0627 \u0627\u0646\u062f\u0627\u0632\u0647 \u06af\u06cc\u0631\u06cc \u06a9\u0646\u06cc\u062f\u060c \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644\u060c <code>eslint<\/code> \u0642\u0627\u0646\u0648\u0646 \u0645\u0631\u062a\u0628 \u0633\u0627\u0632\u06cc \u0648\u0627\u0631\u062f\u0627\u062a \u0627\u062c\u0631\u0627 \u0645\u06cc \u0634\u0648\u062f <code>ast<\/code> \u0645\u0634\u0627\u0647\u062f\u0647 \u062a\u062c\u0632\u06cc\u0647 \u06a9\u0646\u0646\u062f\u0647\u060c \u062f\u0631 \u06cc\u06a9 \u067e\u0631\u0648\u0698\u0647 \u0628\u0632\u0631\u06af \u0641\u0642\u0637 \u0628\u0631\u0627\u06cc \u0645\u062f\u062a \u0637\u0648\u0644\u0627\u0646\u06cc \u06a9\u0627\u0631 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<p>\u062f\u0631 \u0627\u06cc\u0646 \u067e\u0633\u062a \u0646\u0634\u0627\u0646 \u062f\u0627\u062f\u0645 \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0627 \u0646\u0633\u062e\u0647\u200c\u0633\u0627\u0632\u06cc \u0641\u0631\u0627\u0646\u062a\u200c\u0627\u0646\u062f \u0633\u0631\u0639\u062a \u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0631\u0627 \u0627\u0641\u0632\u0627\u06cc\u0634 \u062f\u0647\u06cc\u062f \u0648 \u0647\u0645\u06cc\u0646 \u06a9\u0627\u0631 \u0631\u0627 \u0628\u0627 \u0645\u06cc\u06a9\u0631\u0648\u0633\u0631\u0648\u06cc\u0633\u200c\u0647\u0627 \u0646\u06cc\u0632 \u0627\u0646\u062c\u0627\u0645 \u062f\u0647\u06cc\u062f.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B7%D8%B1%D8%AD_%D9%87%D8%A7\"><\/span>\n<p>  \u0637\u0631\u062d \u0647\u0627<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u0632 \u0622\u0646\u062c\u0627\u06cc\u06cc \u06a9\u0647 \u0645\u0646 \u0645\u0648\u0641\u0642 \u0628\u0647 \u062a\u06a9\u0645\u06cc\u0644 \u0646\u06a9\u0627\u062a \u0627\u0635\u0644\u06cc \u062f\u0631 devops \u0634\u062f\u0645\u060c \u067e\u0633\u062a\u200c\u0647\u0627\u06cc \u0632\u06cc\u0631 \u0642\u0628\u0644\u0627\u064b \u062d\u0627\u0648\u06cc \u062a\u0648\u0636\u06cc\u062d\u0627\u062a \u0645\u062e\u062a\u0635\u0631\u06cc \u0627\u0632 \u062a\u0648\u0633\u0639\u0647 \u0648\u06cc\u0698\u06af\u06cc\u200c\u0647\u0627\u06cc \u0627\u0635\u0644\u06cc \u0627\u0633\u062a \u06a9\u0647 \u0642\u0635\u062f \u0627\u0646\u062c\u0627\u0645 \u0622\u0646 \u0631\u0627 \u062f\u0627\u0634\u062a\u0645.<\/p>\n<p>\u062f\u0631 \u067e\u0633\u062a \u0628\u0639\u062f\u06cc\u060c \u06cc\u06a9 \u0645\u0627\u0698\u0648\u0644 webhook \u062f\u0631 NestJS \u0627\u06cc\u062c\u0627\u062f \u062e\u0648\u0627\u0647\u0645 \u06a9\u0631\u062f \u062a\u0627 \u0627\u0639\u0644\u0627\u0646\u200c\u0647\u0627\u06cc\u06cc \u062f\u0631 \u0645\u0648\u0631\u062f \u0631\u0648\u06cc\u062f\u0627\u062f\u0647\u0627\u06cc\u0645\u0627\u0646 \u0628\u0647 \u0633\u0631\u0648\u06cc\u0633\u200c\u0647\u0627\u06cc \u0634\u062e\u0635 \u062b\u0627\u0644\u062b \u0627\u0631\u0627\u0626\u0647 \u06a9\u0646\u062f&#8230;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D9%BE%DB%8C%D9%88%D9%86%D8%AF%D9%87%D8%A7\"><\/span>\n<p>  \u067e\u06cc\u0648\u0646\u062f\u0647\u0627<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>https:\/\/nestjs.com &#8211; \u0648\u0628 \u0633\u0627\u06cc\u062a \u0631\u0633\u0645\u06cc \u0686\u0627\u0631\u0686\u0648\u0628<br \/>\nhttps:\/\/nestjs-mod.com &#8211; \u0648\u0628 \u0633\u0627\u06cc\u062a \u0631\u0633\u0645\u06cc \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc \u0627\u0636\u0627\u0641\u06cc<br \/>\nhttps:\/\/fullstack.nestjs-mod.com &#8211; \u0648\u0628 \u0633\u0627\u06cc\u062a \u0627\u0632 \u067e\u0633\u062a<br \/>\nhttps:\/\/github.com\/nestjs-mod\/nestjs-mod-fullstack &#8211; \u067e\u0631\u0648\u0698\u0647 \u0627\u0632 \u067e\u0633\u062a<br \/>\nhttps:\/\/github.com\/nestjs-mod\/nestjs-mod-fullstack\/compare\/2f9b6eddb32a9777fabda81afa92d9aaebd432cc..460257364bb4ce8e23fe761fb21c9ca74 &#8211; \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0641\u0639\u0644\u06cc<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summarize this content to 400 words in Persian Lang \u0627\u0632 \u0632\u0645\u0627\u0646\u06cc \u06a9\u0647 \u0646\u0633\u062e\u0647 \u0627\u0632 \u0637\u0631\u06cc\u0642 nx-semantic-release \u0627\u0641\u0632\u0648\u0646\u0647 \u0628\u0627 \u062a\u062c\u0632\u06cc\u0647 \u0648 \u062a\u062d\u0644\u06cc\u0644 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0645\u0631\u0628\u0648\u0637 \u0628\u0647 \u0622\u0646 \u0635\u0648\u0631\u062a \u0645\u06cc \u06af\u06cc\u0631\u062f Typescript \u0648\u0627\u0631\u062f\u0627\u062a\u060c \u0628\u0627\u06cc\u062f \u0627\u06cc\u0646 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0631\u0627 \u0628\u0647 \u062d\u062f\u0627\u0642\u0644 \u0628\u0631\u0633\u0627\u0646\u06cc\u0645\u060c \u0628\u0631\u0627\u06cc \u0627\u0646\u062c\u0627\u0645 \u0627\u06cc\u0646 \u06a9\u0627\u0631\u060c \u0628\u0647 \u067e\u0631\u0648\u0698\u0647 https:\/\/www.npmjs.com\/package\/lint-staged \u0645\u062a\u0635\u0644 \u0645\u06cc \u0634\u0648\u06cc\u0645 \u0648 \u0633\u062e\u062a \u06af\u06cc\u0631\u06cc \u0631\u0627 \u0628\u0647 \u0622\u0646 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc &hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[339],"tags":[],"class_list":["post-77048","post","type-post","status-publish","format-standard","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/77048","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/comments?post=77048"}],"version-history":[{"count":0,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/77048\/revisions"}],"wp:attachment":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media?parent=77048"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/categories?post=77048"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/tags?post=77048"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}