เด’เดฐเต เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเต เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเดฒเต† เด•เดพเดฒเดนเดฐเดฃเดชเตเดชเต†เดŸเตเดŸ เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเต เดจเต€เด•เตเด•เด‚เดšเต†เดฏเตเดฏเตเดจเตเดจเต

เด’เดฐเต เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเต เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเดฒเต† เด•เดพเดฒเดนเดฐเดฃเดชเตเดชเต†เดŸเตเดŸ เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเต เดจเต€เด•เตเด•เด‚เดšเต†เดฏเตเดฏเตเดจเตเดจเต

เดนเดฒเต‹! เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเต (เด…เดคเดพเดฏเดคเต เดตเดฟเดจเตเดฏเดธเดฟเด•เตเด•เตเด• เดชเตเดฐเดฟเดตเตเดฏเต‚, เดฑเดฟเดตเตเดฏเต‚ เด†เดชเตเดชเต) - เด‡เดคเต เดฎเดพเดธเตเดฑเตเดฑเตผ เดฌเตเดฐเดพเดžเตเดšเต เดตเดฟเดจเตเดฏเดธเดฟเด•เตเด•เตเดฎเตเดชเต‹เตพ เดฎเดพเดคเตเดฐเดฎเดฒเตเดฒ, เด“เดฐเต‹ เด…เดญเตเดฏเตผเดคเตเดฅเดจเดฏเตเด‚ เด’เดฐเต เด…เดฆเตเดตเดฟเดคเต€เดฏ URL-เดฒเต‡เดฏเตเด•เตเด•เดพเดฃเต. เด’เดฐเต เดชเตเดฐเตŠเดกเด•เตเดทเตป เดชเดฐเดฟเดคเดธเตเดฅเดฟเดคเดฟเดฏเดฟเตฝ เด•เต‹เดกเต เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเตเดฃเตเดŸเต‹เดฏเต†เดจเตเดจเต เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เดพเด‚; เดซเต€เดšเตเดšเตผ เดฎเดฑเตเดฑเต เดชเตเดฐเต‹เด—เตเดฐเดพเดฎเตผเดฎเดพเตผเด•เตเด•เต‹ เด‰เตฝเดชเตเดชเดจเตเดจ เดธเตเดชเต†เดทเตเดฏเดฒเดฟเดธเตเดฑเตเดฑเตเด•เตพเด•เตเด•เต‹ โ€‹โ€‹เด•เดพเดฃเดฟเด•เตเด•เดพเดจเดพเด•เตเด‚. เดจเดฟเด™เตเด™เตพ เด’เดฐเต เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจเดฏเดฟเตฝ เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดฎเตเดชเต‹เตพ, เดชเดดเดฏ เด•เต‹เดกเดฟเดจเดพเดฏเตเดณเตเดณ เด“เดฐเต‹ เดชเตเดคเดฟเดฏ เด•เดฎเตเดฎเดฟเดฑเตเดฑเต เด•เดฑเดจเตเดฑเต เดกเดฟเดชเตเดฒเต‹เดฏเตเด‚ เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เดชเตเดชเต†เดŸเตเด‚, เดชเตเดคเดฟเดฏ เด•เต‹เดกเดฟเดจเดพเดฏเดฟ เดชเตเดคเดฟเดฏ เดตเดฟเดจเตเดฏเดพเดธเด‚ เดชเตเดฑเดคเตเดคเดฟเดฑเด•เตเด•เตเด‚. เดจเดฟเด™เตเด™เตพ เด’เดฐเต เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจ เดฎเดพเดธเตเดฑเตเดฑเตผ เดฌเตเดฐเดพเดžเตเดšเดฟเดฒเต‡เด•เตเด•เต เดฒเดฏเดฟเดชเตเดชเดฟเด•เตเด•เตเดฎเตเดชเต‹เตพ เดšเต‹เดฆเตเดฏเด™เตเด™เตพ เด‰เดฏเตผเดจเตเดจเต‡เด•เตเด•เดพเด‚. เดจเดฟเด™เตเด™เตพเด•เตเด•เต เด‡เดจเดฟ เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเต เด†เดตเดถเตเดฏเดฎเดฟเดฒเตเดฒ, เดŽเดจเตเดจเดพเตฝ เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเต เด‰เดฑเดตเดฟเดŸเด™เตเด™เตพ เด‡เดชเตเดชเต‹เดดเตเด‚ เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเดฒเดพเดฃเต.

เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเตเด•เดณเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เด•เต‚เดŸเตเดคเตฝ

เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเดฟเตฝ เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเตเด•เตพ เด‰เดฃเตเดŸเดพเด•เตเด•เตเดจเตเดจเดคเดฟเดจเตเดณเตเดณ เด’เดฐเต เดธเดฎเต€เดชเดจเด‚ เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเตเด•เตพ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเด• เดŽเดจเตเดจเดคเดพเดฃเต. เดšเตเดฐเตเด•เตเด•เดคเตเดคเดฟเตฝ, เดชเตเดฐเตŠเดกเด•เตเดทเตป เด•เต‹เตบเดซเดฟเด—เดฑเต‡เดทเตป เด‡เดคเตเดชเต‹เดฒเต† เด•เดพเดฃเดชเตเดชเต†เดŸเตเดจเตเดจเต:

kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end
spec:
  replicas: 3
...

เด’เดฐเต เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเดฟเดจเดพเดฏเดฟ, เด’เดฐเต เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเต เด…เดคเดฟเดจเตเดฑเต† เดเดกเดจเตเดฑเดฟเดซเดฏเดฑเตเด‚ (เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจ เดจเดฎเตเดชเตผ) เดšเดฟเดฒ เดคเดฐเดคเตเดคเดฟเดฒเตเดณเตเดณ เดชเตเดฐเดฟเดซเดฟเด•เตเดธเตเด‚/เดชเต‹เดธเตเดฑเตเดฑเตเดซเดฟเด•เตเดธเตเด‚ (เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, -pr-):

kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end-pr-17
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end-pr-17
spec:
  replicas: 1
...

เดชเตŠเดคเตเดตเต‡, เดžเดพเตป เดŽเดดเตเดคเดฟ เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเต เด“เดชเตเดชเดฑเต‡เดฑเตเดฑเตผ (เด•เตเดฒเดธเตเดฑเตเดฑเตผ เด‰เดฑเดตเดฟเดŸเด™เตเด™เดณเดฟเดฒเต‡เด•เตเด•เต เด†เด•เตโ€Œเดธเดธเต เด‰เดณเตเดณ เด’เดฐเต เด†เดชเตเดฒเดฟเด•เตเด•เต‡เดทเตป), Github-เดฒเต† เดชเดฆเตเดงเดคเดฟเดฏเดฟเดฒเต‡เด•เตเด•เตเดณเตเดณ เดฒเดฟเด™เตเด•เต. เดชเดดเดฏ เดซเต€เดšเตเดšเตผ เดถเดพเด–เด•เดณเตเดŸเต‡เดคเดพเดฏ เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเตเด•เตพ เด‡เดคเต เดจเต€เด•เตเด•เด‚ เดšเต†เดฏเตเดฏเตเดจเตเดจเต. เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเดฟเตฝ, เดจเดฟเด™เตเด™เตพ เด’เดฐเต เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเต เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เตเด•เดฏเดพเดฃเต†เด™เตเด•เดฟเตฝ, เด† เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเดฟเดฒเต† เดฎเดฑเตเดฑเต เด‰เดฑเดตเดฟเดŸเด™เตเด™เดณเตเด‚ เดธเตเดตเดฏเดฎเต‡เดต เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เดชเตเดชเต†เดŸเตเด‚.

$ kubectl get pods --all-namespaces | grep -e "-pr-"
NAMESPACE            ... AGE
habr-back-end-pr-264 ... 4d8h
habr-back-end-pr-265 ... 5d7h

เด’เดฐเต เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเดฒเต‡เด•เตเด•เต เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเตเด•เตพ เดŽเด™เตเด™เดจเต† เดจเดŸเดชเตเดชเดฟเดฒเดพเด•เตเด•เดพเด‚ เดŽเดจเตเดจเดคเดฟเดจเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดตเดพเดฏเดฟเด•เตเด•เดพเด‚ เด‡เดตเดฟเดŸเต† ะธ เด‡เดตเดฟเดŸเต†.

เดชเตเดฐเดšเต‹เดฆเดจเด‚

เดคเตเดŸเตผเดšเตเดšเดฏเดพเดฏ เดธเด‚เดฏเต‹เดœเดจเดคเตเดคเต‹เดŸเต†เดฏเตเดณเตเดณ เด’เดฐเต เดธเดพเดงเดพเดฐเดฃ เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจ เดœเต€เดตเดฟเดคเดšเด•เตเดฐเด‚ เดจเต‹เด•เตเด•เดพเด‚ (continuous integration):

  1. เดžเด™เตเด™เตพ เดฌเตเดฐเดพเดžเตเดšเดฟเดฒเต‡เด•เตเด•เต เด’เดฐเต เดชเตเดคเดฟเดฏ เดชเตเดฐเดคเดฟเดฌเดฆเตเดงเดค เดจเตฝเด•เตเดจเตเดจเต.
  2. เดจเดฟเตผเดฎเตเดฎเดพเดฃเดคเตเดคเดฟเตฝ, เดฒเดฟเดจเตเดฑเดฑเตเด•เตพ เด•เต‚เดŸเดพเดคเต†/เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เดชเดฐเดฟเดถเต‹เดงเดจเด•เตพ เดจเดŸเดคเตเดคเตเดจเตเดจเต.
  3. เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเต เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจ เด•เต‹เตบเดซเดฟเด—เดฑเต‡เดทเดจเตเด•เตพ เดซเตเดฒเตˆเดฏเดฟเตฝ เดœเดจเดฑเต‡เดฑเตเดฑเตเดšเต†เดฏเตเดฏเตเดจเตเดจเต (เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, เดชเต‚เตผเดคเตเดคเดฟเดฏเดพเดฏ เดŸเต†เด‚เดชเตเดฒเต‡เดฑเตเดฑเดฟเตฝ เด…เดคเดฟเดจเตเดฑเต† เดจเดฎเตเดชเตผ เดšเต‡เตผเดคเตเดคเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเต).
  4. kubectl apply เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต, เด•เต‹เตบเดซเดฟเด—เดฑเต‡เดทเดจเตเด•เตพ เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเดฒเต‡เด•เตเด•เต เดšเต‡เตผเด•เตเด•เตเดจเตเดจเต (เดตเดฟเดจเตเดฏเดพเดธเด‚).
  5. เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจ เดฎเดพเดธเตเดฑเตเดฑเตผ เดฌเตเดฐเดพเดžเตเดšเดฟเดฒเต‡เด•เตเด•เต เดฒเดฏเดฟเดชเตเดชเดฟเดšเตเดšเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเต.

เดจเดฟเด™เตเด™เตพ เด’เดฐเต เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจเดฏเดฟเตฝ เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดฎเตเดชเต‹เตพ, เดชเดดเดฏ เด•เต‹เดกเดฟเดจเดพเดฏเตเดณเตเดณ เด“เดฐเต‹ เดชเตเดคเดฟเดฏ เด•เดฎเตเดฎเดฟเดฑเตเดฑเต เด•เดฑเดจเตเดฑเต เดกเดฟเดชเตเดฒเต‹เดฏเตเด‚ เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เดชเตเดชเต†เดŸเตเด‚, เดชเตเดคเดฟเดฏ เด•เต‹เดกเดฟเดจเดพเดฏเดฟ เดชเตเดคเดฟเดฏ เดตเดฟเดจเตเดฏเดพเดธเด‚ เดชเตเดฑเดคเตเดคเดฟเดฑเด•เตเด•เตเด‚. เดŽเดจเตเดจเดพเตฝ เด’เดฐเต เดชเตเตพ เดฑเดฟเด•เตเดตเดธเตเดฑเตเดฑเต เดฎเดพเดธเตเดฑเตเดฑเตผ เดฌเตเดฐเดพเดžเตเดšเดฟเตฝ เดฒเดฏเดฟเดชเตเดชเดฟเด•เตเด•เตเดฎเตเดชเต‹เตพ, เดฎเดพเดธเตเดฑเตเดฑเตผ เดฌเตเดฐเดพเดžเตเดšเต เดฎเดพเดคเตเดฐเดฎเต‡ เดจเดฟเตผเดฎเตเดฎเดฟเด•เตเด•เดชเตเดชเต†เดŸเตเด•เดฏเตเดณเตเดณเต‚. เดคเตฝเดซเดฒเดฎเดพเดฏเดฟ, เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจเดฏเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เดžเด™เตเด™เตพ เด‡เดคเดฟเดจเด•เด‚ เดฎเดฑเดจเตเดจเตเดตเต†เดจเตเดจเตเด‚ เด…เดคเดฟเดจเตเดฑเต† เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเต เด‰เดฑเดตเดฟเดŸเด™เตเด™เตพ เด‡เดชเตเดชเต‹เดดเตเด‚ เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเดฒเดพเดฃเต†เดจเตเดจเตเด‚ เด‡เดคเต เดฎเดพเดฑเตเดจเตเดจเต.

เดŽเด™เตเด™เดจเต† เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเด‚

เดšเตเดตเดŸเต†เดฏเตเดณเตเดณ เด•เดฎเดพเตปเดกเต เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดชเตเดฐเต‹เดœเด•เตเดฑเตเดฑเต เด‡เตปเดธเตเดฑเตเดฑเดพเตพ เดšเต†เดฏเตเดฏเตเด•:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml

เด‡เดจเดฟเดชเตเดชเดฑเดฏเตเดจเตเดจ เด‰เดณเตเดณเดŸเด•เตเด•เด‚ เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เด’เดฐเต เดซเดฏเตฝ เดธเตƒเดทเตโ€ŒเดŸเดฟเดšเตเดšเต เด‡เดคเต เดตเดดเดฟ เด‡เตปเดธเตเดฑเตเดฑเดพเตพ เดšเต†เดฏเตเดฏเตเด• kubectl apply -f:

apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 3

เดชเดพเดฐเดพเดฎเต€เดฑเตเดฑเตผ namespaceSubstring เดฎเดฑเตเดฑเต เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเตเด•เดณเดฟเตฝ เดจเดฟเดจเตเดจเตเดณเตเดณ เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจเด•เตพเด•เตเด•เดพเดฏเดฟ เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเตเด•เตพ เดซเดฟเตฝเดŸเตเดŸเตผ เดšเต†เดฏเตเดฏเต‡เดฃเตเดŸเดคเต เด†เดตเดถเตเดฏเดฎเดพเดฃเต. เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเดจเต เด‡เดจเดฟเดชเตเดชเดฑเดฏเตเดจเตเดจ เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเต เด‰เดฃเตเดŸเต†เด™เตเด•เดฟเตฝ: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, เด…เดชเตเดชเต‹เตพ เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เดพเดจเตเดณเตเดณ เดธเตเดฅเดพเดจเดพเตผเดคเตเดฅเดฟเด•เตพ เด†เดฏเดฟเดฐเดฟเด•เตเด•เตเด‚ habr-back-end-pr-17, habr-back-end-pr-33.

เดชเดพเดฐเดพเดฎเต€เดฑเตเดฑเตผ เดถเต‡เดทเด‚Days WithoutDeploy เดชเดดเดฏ เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเตเด•เตพ เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต. เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเต เดธเตƒเดทเตเดŸเดฟเดšเตเดšเดพเตฝ 3 ะดะฝั 1 ั‡ะฐั เดคเดฟเดฐเดฟเด•เต†, เด’เดชเตเดชเด‚ เดชเดฐเดพเดฎเต€เดฑเตเดฑเตผ เดธเต‚เดšเดฟเดชเตเดชเดฟเด•เตเด•เตเดจเตเดจเต 3 ะดะฝั, เดˆ เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเต เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เดชเตเดชเต†เดŸเตเด‚. เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเต เด‰เดฃเตเดŸเดพเด•เตเด•เดฟเดฏเดพเตฝ เด…เดคเต เดตเดฟเดชเดฐเต€เดค เดฆเดฟเดถเดฏเดฟเดฒเตเด‚ เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเต 2 ะดะฝั 23 ั‡ะฐัะฐ เดคเดฟเดฐเดฟเด•เต†, เด’เดชเตเดชเด‚ เดชเดฐเดพเดฎเต€เดฑเตเดฑเตผ เดธเต‚เดšเดฟเดชเตเดชเดฟเด•เตเด•เตเดจเตเดจเต 3 ะดะฝั, เดˆ เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเต เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เดฟเดฒเตเดฒ.

เด’เดฐเต เดชเดพเดฐเดพเดฎเต€เดฑเตเดฑเตผ เด•เต‚เดŸเดฟเดฏเตเดฃเตเดŸเต, เดŽเดฒเตเดฒเดพ เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเตเด•เดณเตเด‚ เดŽเดคเตเดฐ เดคเดตเดฃ เดธเตโ€Œเด•เดพเตป เดšเต†เดฏเตเดฏเดฃเดฎเต†เดจเตเดจเตเด‚ เดตเดฟเดจเตเดฏเดพเดธเด‚ เด•เต‚เดŸเดพเดคเต† เดฆเดฟเดตเดธเด™เตเด™เตพ เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เดฃเดฎเต†เดจเตเดจเตเด‚ เด‡เดคเต เด‰เดคเตเดคเดฐเดตเดพเดฆเดฟเดฏเดพเดฃเต - เด“เดฐเต‹ เดฎเดฟเดจเดฟเดฑเตเดฑเดฟเดฒเตเด‚ เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เตเด•. เดธเตเดฅเดฟเดฐเดธเตเดฅเดฟเดคเดฟเดฏเดพเดฏเดฟ เด‡เดคเต เดคเตเดฒเตเดฏเดฎเดพเดฃเต 30 ะผะธะฝัƒั‚ะฐะผ.

เดŽเด™เตเด™เดจเต† เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเดฟเดฒเตเดฒ

เดชเตเดฐเดพเดฏเต‹เด—เดฟเด•เดฎเดพเดฏเดฟ, เดจเดฟเด™เตเด™เตพเด•เตเด•เต เด‡เดคเต เด†เดตเดถเตเดฏเดฎเดพเดฃเต:

  1. เดกเต‹เด•เตเด•เตผ เด’เดฑเตเดฑเดชเตเดชเต†เดŸเตเดŸ เด…เดจเตเดคเดฐเต€เด•เตเดทเดคเตเดคเดฟเตฝ เดœเต‹เดฒเดฟ เดšเต†เดฏเตเดคเดคเดฟเดจเต.
  2. เดฎเดฟเดจเดฟเด•เตเดฏเต‚เดฌเต เดชเตเดฐเดพเดฆเต‡เดถเดฟเด•เดฎเดพเดฏเดฟ เด’เดฐเต เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเต เด•เตเดฒเดธเตเดฑเตเดฑเตผ เด‰เดฏเตผเดคเตเดคเตเด‚.
  3. เด•เตเดฌเต†เด•เตเดฒเดฟ โ€” เด•เตเดฒเดธเตเดฑเตเดฑเตผ เดฎเดพเดจเต‡เดœเตเดฎเต†เดจเตเดฑเดฟเดจเตเดณเตเดณ เด•เดฎเดพเตปเดกเต เดฒเตˆเตป เด‡เดจเตเดฑเตผเดซเต‡เดธเต.

เดžเด™เตเด™เตพ เดชเตเดฐเดพเดฆเต‡เดถเดฟเด•เดฎเดพเดฏเดฟ เด’เดฐเต เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเต เด•เตเดฒเดธเตเดฑเตเดฑเตผ เดตเดณเตผเดคเตเดคเตเดจเตเดจเต:

$ minikube start --vm-driver=docker
minikube v1.11.0 on Darwin 10.15.5
Using the docker driver based on existing profile.
Starting control plane node minikube in cluster minikube.

เดธเต‚เดšเดฟเดชเตเดชเดฟเด•เตเด•เตเด• kubectl เดธเตเดฅเดฟเดฐเดธเตเดฅเดฟเดคเดฟเดฏเดพเดฏเดฟ เดชเตเดฐเดพเดฆเต‡เดถเดฟเด• เด•เตเดฒเดธเตเดฑเตเดฑเตผ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเด•:

$ kubectl config use-context minikube
Switched to context "minikube".

เด‰เตฝเดชเตเดชเดพเดฆเดจ เด…เดจเตเดคเดฐเต€เด•เตเดทเดคเตเดคเดฟเดจเดพเดฏเตเดณเตเดณ เด•เต‹เตบเดซเดฟเด—เดฑเต‡เดทเดจเตเด•เตพ เดกเต—เตบเดฒเต‹เดกเต เดšเต†เดฏเตเดฏเตเด•:

$ curl https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml > stale-feature-branch-production-configs.yml

เดชเดดเดฏ เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเตเด•เตพ เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเดพเดฏเดฟ เดชเตเดฐเตŠเดกเด•เตเดทเตป เด•เต‹เตบเดซเดฟเด—เดฑเต‡เดทเดจเตเด•เตพ เด•เตเดฐเดฎเต€เด•เดฐเดฟเดšเตเดšเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเดพเดฒเตเด‚ เดžเด™เตเด™เดณเตเดŸเต† เดชเตเดคเตเดคเดพเดฏเดฟ เด‰เดฏเตผเดคเตเดคเดฟเดฏ เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเตฝ เด…เดต เด‡เดฒเตเดฒเดพเดคเตเดคเดคเดฟเดจเดพเดฒเตเด‚, เดžเด™เตเด™เตพ เดชเดฐเดฟเดธเตเดฅเดฟเดคเดฟ เดตเต‡เดฐเดฟเดฏเดฌเดฟเดณเดฟเดจเต† เดฎเดพเดฑเตเดฑเดฟเดธเตเดฅเดพเดชเดฟเด•เตเด•เตเด‚. IS_DEBUG เด“เตบ true. เดˆ เดฎเต‚เดฒเตเดฏเด‚ เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดชเดฐเดพเดฎเต€เดฑเตเดฑเตผ afterDaysWithoutDeploy เดŽเดจเตเดจเดคเต เด•เดฃเด•เตเด•เดฟเดฒเต†เดŸเตเด•เตเด•เตเดจเตเดจเดฟเดฒเตเดฒ เด•เต‚เดŸเดพเดคเต† เดตเดฟเดจเตเดฏเดธเดฟเด•เตเด•เดพเดคเต† เดฆเดฟเดตเดธเด™เตเด™เดณเต‹เดณเด‚ เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเต เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เดฟเดฒเตเดฒ, เดธเดฌเตโ€Œเดธเตโ€ŒเดŸเตเดฐเดฟเด‚เด—เดฟเดจเตเดฑเต† เดธเด‚เดญเดตเดคเตเดคเดฟเดจเต เดตเต‡เดฃเตเดŸเดฟ เดฎเดพเดคเตเดฐเด‚ (-pr-).

เดจเดฟเด™เตเด™เตพ เด“เดฃเดพเดฃเต†เด™เตเด•เดฟเตฝ Linux:

$ sed -i 's|false|true|g' stale-feature-branch-production-configs.yml

เดจเดฟเด™เตเด™เตพ เด“เดฃเดพเดฃเต†เด™เตเด•เดฟเตฝ macOS:

$ sed -i "" 's|false|true|g' stale-feature-branch-production-configs.yml

เดชเตเดฐเต‹เดœเด•เตเดฑเตเดฑเต เด‡เตปเดธเตเดฑเตเดฑเดพเตพ เดšเต†เดฏเตเดฏเตเดจเตเดจเต:

$ kubectl apply -f stale-feature-branch-production-configs.yml

เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเตฝ เด’เดฐเต เด‰เดฑเดตเดฟเดŸเด‚ เดชเตเดฐเดคเตเดฏเด•เตเดทเดชเตเดชเต†เดŸเตเดŸเดฟเดŸเตเดŸเตเดฃเตเดŸเต‹เดฏเต†เดจเตเดจเต เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เตเดจเตเดจเต StaleFeatureBranch:

$ kubectl api-resources | grep stalefeaturebranches
NAME                 ... APIGROUP                             ... KIND
stalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranch

เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเตฝ เด’เดฐเต เด“เดชเตเดชเดฑเต‡เดฑเตเดฑเตผ เดชเตเดฐเดคเตเดฏเด•เตเดทเดชเตเดชเต†เดŸเตเดŸเดฟเดŸเตเดŸเตเดฃเตเดŸเต‹เดฏเต†เดจเตเดจเต เดžเด™เตเด™เตพ เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เตเดจเตเดจเต:

$ kubectl get pods --namespace stale-feature-branch-operator
NAME                                           ... STATUS  ... AGE
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Running ... 38s

เดจเดฟเด™เตเด™เตพ เด…เดคเดฟเดจเตเดฑเต† เดฒเต‹เด—เตเด•เตพ เดจเต‹เด•เตเด•เตเด•เดฏเดพเดฃเต†เด™เตเด•เดฟเตฝ, เด…เดคเต เด‰เดฑเดตเดฟเดŸเด™เตเด™เตพ เดชเตเดฐเต‹เดธเดธเตเดธเต เดšเต†เดฏเตเดฏเดพเตป เดคเดฏเตเดฏเดพเดฑเดพเดฃเต StaleFeatureBranch:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Operator Version: 0.0.1"}
...
... "msg":"Starting EventSource", ... , "source":"kind source: /, Kind="}
... "msg":"Starting Controller", ...}
... "msg":"Starting workers", ..., "worker count":1}

เดžเด™เตเด™เตพ เดฑเต†เดกเดฟเดฎเต†เดฏเตเดกเต เด‡เตปเดธเตเดฑเตเดฑเดพเตพ เดšเต†เดฏเตเดฏเตเดจเตเดจเต fixtures เด’เดฐเต เดฑเดฟเดธเต‹เดดเตเดธเดฟเดจเดพเดฏเดฟ (เด•เตเดฒเดธเตเดฑเตเดฑเตผ เด‰เดฑเดตเดฟเดŸเด™เตเด™เตพ เดฎเต‹เดกเดฒเดฟเด‚เด—เต เดšเต†เดฏเตเดฏเตเดจเตเดจเดคเดฟเดจเตเดณเตเดณ เดฑเต†เดกเดฟเดฎเต†เดฏเตเดกเต เด•เต‹เตบเดซเดฟเด—เดฑเต‡เดทเดจเตเด•เตพ). StaleFeatureBranch:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/stale-feature-branch.yml

เด’เดฐเต เดธเดฌเตโ€ŒเดธเตเดŸเตเดฐเดฟเด‚เด—เต เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเตเด•เตพเด•เตเด•เดพเดฏเดฟ เดคเดฟเดฐเดฏเดพเตป เด•เต‹เตบเดซเดฟเด—เดฑเต‡เดทเดจเตเด•เตพ เดธเต‚เดšเดฟเดชเตเดชเดฟเด•เตเด•เตเดจเตเดจเต -pr- เด’เดฐเดฟเด•เตเด•เตฝ 1 ะผะธะฝัƒั‚ัƒ.:

apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 1 
  checkEveryMinutes: 1

เด“เดชเตเดชเดฑเต‡เดฑเตเดฑเตผ เดชเตเดฐเดคเดฟเด•เดฐเดฟเดšเตเดšเต เด•เต‚เดŸเดพเดคเต† เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเตเด•เตพ เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เดพเตป เดคเดฏเตเดฏเดพเดฑเดพเดฃเต:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Stale feature branch is being processing.","namespaceSubstring":"-pr-","afterDaysWithoutDeploy":1,"checkEveryMinutes":1,"isDebug":"true"}

เด‡เตปเดธเตเดฑเตเดฑเดพเตพ เดšเต†เดฏเตเดฏเตเด• fixtures, เดฐเดฃเตเดŸเต เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเต เด…เดŸเด™เตเด™เดฟเดฏเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเต (project-pr-1, project-pr-2) เด…เดตเดฐเตเด‚ deployments, services, ingress, เด‡เดคเตเดฏเดพเดฆเดฟ:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/first-feature-branch.yml -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/second-feature-branch.yml
...
namespace/project-pr-1 created
deployment.apps/project-pr-1 created
service/project-pr-1 created
horizontalpodautoscaler.autoscaling/project-pr-1 created
secret/project-pr-1 created
configmap/project-pr-1 created
ingress.extensions/project-pr-1 created
namespace/project-pr-2 created
deployment.apps/project-pr-2 created
service/project-pr-2 created
horizontalpodautoscaler.autoscaling/project-pr-2 created
secret/project-pr-2 created
configmap/project-pr-2 created
ingress.extensions/project-pr-2 created

เดฎเตเด•เดณเดฟเดฒเตเดณเตเดณ เดŽเดฒเตเดฒเดพ เด‰เดฑเดตเดฟเดŸเด™เตเด™เดณเตเด‚ เดตเดฟเดœเดฏเด•เดฐเดฎเดพเดฏเดฟ เดธเตƒเดทเตเดŸเดฟเดšเตเดšเดฟเดŸเตเดŸเตเดฃเตเดŸเต‹เดฏเต†เดจเตเดจเต เดžเด™เตเด™เตพ เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เตเดจเตเดจเต:

$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...
NAME                              ... READY ... STATUS  ... AGE
pod/project-pr-1-848d5fdff6-rpmzw ... 1/1   ... Running ... 67s

NAME                         ... READY ... AVAILABLE ... AGE
deployment.apps/project-pr-1 ... 1/1   ... 1         ... 67s
...

เดžเด™เตเด™เตพ เด‰เตพเดชเตเดชเต†เดŸเตเดคเตเดคเดฟเดฏเดคเดฟเดจเดพเตฝ debug, เดจเต†เดฏเดฟเด‚เดธเตเดชเต‡เดธเตเด•เตพ project-pr-1 ะธ project-pr-2, เด…เดคเดฟเดจเดพเตฝ เดชเดพเดฐเดพเดฎเต€เดฑเตเดฑเตผ เด•เดฃเด•เตเด•เดฟเดฒเต†เดŸเตเด•เตเด•เดพเดคเต† เดฎเดฑเตเดฑเต†เดฒเตเดฒเดพ เด‰เดฑเดตเดฟเดŸเด™เตเด™เดณเตเด‚ เด‰เดŸเดจเดŸเดฟ เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต afterDaysWithoutDeploy. เด“เดชเตเดชเดฑเต‡เดฑเตเดฑเตผ เดฒเต‹เด—เตเด•เดณเดฟเตฝ เด‡เดคเต เด•เดพเดฃเดพเตป เด•เดดเดฟเดฏเตเด‚:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-1"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-1","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-1"}
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-2"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-2","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-2"}

เดจเดฟเด™เตเด™เตพ เดตเดฟเดญเดตเด™เตเด™เดณเตเดŸเต† เดฒเดญเตเดฏเดค เดชเดฐเดฟเดถเต‹เดงเดฟเดšเตเดšเดพเตฝ, เด…เดต เดธเตเดฑเตเดฑเดพเดฑเตเดฑเดธเต เด†เดฏเดฟเดฐเดฟเด•เตเด•เตเด‚ Terminating (เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เตฝ เดชเตเดฐเด•เตเดฐเดฟเดฏ) เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เด‡เดคเดฟเดจเด•เด‚ เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เดฟ (เด•เดฎเดพเตปเดกเต เด”เดŸเตเดŸเตเดชเตเดŸเตเดŸเต เดถเต‚เดจเตเดฏเดฎเดพเดฃเต).

$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...

เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดธเตƒเดทเตเดŸเดฟเด•เตเด•เตฝ เดชเตเดฐเด•เตเดฐเดฟเดฏ เด†เดตเตผเดคเตเดคเดฟเด•เตเด•เดพเด‚ fixtures เดจเดฟเดฐเดตเดงเดฟ เดคเดตเดฃ, เด’เดฐเต เดฎเดฟเดจเดฟเดฑเตเดฑเดฟเดจเตเดณเตเดณเดฟเตฝ เด…เดต เดจเต€เด•เตเด•เด‚ เดšเต†เดฏเตเดฏเดชเตเดชเต†เดŸเตเดฎเต†เดจเตเดจเต เด‰เดฑเดชเตเดชเดพเด•เตเด•เตเด•.

เด‡เดคเดฐเดฎเดพเตผเด—เด™เตเด™เตพ

เด’เดฐเต เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเตฝ เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจ เด’เดฐเต เด“เดชเตเดชเดฑเต‡เดฑเตเดฑเตผเด•เตเด•เต เดชเด•เดฐเด‚ เดŽเดจเตเดคเต เดšเต†เดฏเตเดฏเดพเตป เด•เดดเดฟเดฏเตเด‚? เดจเดฟเดฐเดตเดงเดฟ เดธเดฎเต€เดชเดจเด™เตเด™เดณเตเดฃเตเดŸเต, เด…เดตเดฏเต†เดฒเตเดฒเดพเด‚ เด…เดชเต‚เตผเดฃเตเดฃเดฎเดพเดฃเต (เด…เดตเดฏเตเดŸเต† เดชเต‹เดฐเดพเดฏเตเดฎเด•เตพ เด†เดคเตเดฎเดจเดฟเดทเตเด เดฎเดพเดฃเต), เด•เต‚เดŸเดพเดคเต† เด’เดฐเต เดชเตเดฐเดคเตเดฏเต‡เด• เดชเตเดฐเต‹เดœเด•เตเดฑเตเดฑเดฟเดจเต เดเดฑเตเดฑเดตเตเด‚ เดฎเดฟเด•เดšเตเดšเดคเต เดŽเดจเตเดคเดพเดฃเต†เดจเตเดจเต เดŽเดฒเตเดฒเดพเดตเดฐเตเด‚ เดธเตเดตเดฏเด‚ เดคเต€เดฐเตเดฎเดพเดจเดฟเด•เตเด•เตเดจเตเดจเต:

  1. เดฎเดพเดธเตเดฑเตเดฑเตผ เดฌเตเดฐเดพเดžเตเดšเดฟเดจเตเดฑเต† เดคเตเดŸเตผเดšเตเดšเดฏเดพเดฏ เดธเด‚เดฏเต‹เดœเดจ เดธเดฎเดฏเดคเตเดคเต เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเต เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เตเด•.

    • เด‡เดคเต เดšเต†เดฏเตเดฏเตเดจเตเดจเดคเดฟเดจเต, เดเดคเต เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจเดฏเดพเดฃเต เดจเดฟเตผเดฎเตเดฎเดฟเด•เตเด•เตเดจเตเดจ เดชเตเดฐเดคเดฟเดฌเดฆเตเดงเดคเดฏเตเดฎเดพเดฏเดฟ เดฌเดจเตเดงเดชเตเดชเต†เดŸเตเดŸเดคเต†เดจเตเดจเต เดจเดฟเด™เตเด™เตพ เด…เดฑเดฟเดฏเต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต. เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเต เดจเต†เดฏเดฟเด‚เดธเตโ€Œเดชเต†เดฏเตโ€Œเดธเดฟเตฝ เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจ เดเดกเดจเตเดฑเดฟเดซเดฏเตผ เด…เดŸเด™เตเด™เดฟเดฏเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเดพเตฝ - เด…เดคเดฟเดจเตเดฑเต† เดจเดฎเตเดชเตผ เด…เดฒเตเดฒเต†เด™เตเด•เดฟเตฝ เดฌเตเดฐเดพเดžเตเดšเดฟเดจเตเดฑเต† เดชเต‡เดฐเต, เดเดกเดจเตเดฑเดฟเดซเดฏเตผ เดŽเดฒเตเดฒเดพเดฏเตเดชเตเดชเต‹เดดเตเด‚ เด•เดฎเตเดฎเดฟเดฑเตเดฑเดฟเตฝ เดตเตเดฏเด•เตเดคเดฎเดพเด•เตเด•เต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต.
    • เดฎเดพเดธเตเดฑเตเดฑเตผ เดฌเตเดฐเดพเดžเตเดšเต เดจเดฟเตผเดฎเตเดฎเดพเดฃเด‚ เดชเดฐเดพเดœเดฏเดชเตเดชเต†เดŸเตเดจเตเดจเต. เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, เดจเดฟเด™เตเด™เตพเด•เตเด•เต เด‡เดจเดฟเดชเตเดชเดฑเดฏเตเดจเตเดจ เด˜เดŸเตเดŸเด™เตเด™เดณเตเดฃเตเดŸเต: เดชเตเดฐเต‹เดœเด•เตเดฑเตเดฑเต เดกเต—เตบเดฒเต‹เดกเต เดšเต†เดฏเตเดฏเตเด•, เดŸเต†เดธเตเดฑเตเดฑเตเด•เตพ เดชเตเดฐเดตเตผเดคเตเดคเดฟเดชเตเดชเดฟเด•เตเด•เตเด•, เดชเตเดฐเต‹เดœเด•เตเดฑเตเดฑเต เดจเดฟเตผเดฎเตเดฎเดฟเด•เตเด•เตเด•, เดฑเดฟเดฒเต€เดธเต เดšเต†เดฏเตเดฏเตเด•, เด…เดฑเดฟเดฏเดฟเดชเตเดชเตเด•เตพ เด…เดฏเดฏเตเด•เตเด•เตเด•, เด…เดตเดธเดพเดจเดคเตเดคเต† เดชเตเตพ เด…เดญเตเดฏเตผเดคเตเดฅเดจเดฏเตเดŸเต† เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเต เดฎเดพเดฏเตโ€Œเด•เตเด•เตเด•. เด’เดฐเต เด…เดฑเดฟเดฏเดฟเดชเตเดชเต เด…เดฏเดฏเตโ€Œเด•เตเด•เตเดฎเตเดชเต‹เตพ เดฌเดฟเตฝเดกเต เดชเดฐเดพเดœเดฏเดชเตเดชเต†เดŸเตเด•เดฏเดพเดฃเต†เด™เตเด•เดฟเตฝ, เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเดฒเต† เดŽเดฒเตเดฒเดพ เด‰เดฑเดตเดฟเดŸเด™เตเด™เดณเตเด‚ เดจเดฟเด™เตเด™เตพ เดธเตเดตเดฎเต‡เดงเดฏเดพ เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต.
    • เดถเดฐเดฟเดฏเดพเดฏ เดธเดจเตเดฆเตผเดญเดฎเดฟเดฒเตเดฒเดพเดคเต†, เดฎเดพเดธเตเดฑเตเดฑเตผ เดฌเดฟเตฝเดกเดฟเดฒเต† เดซเต€เดšเตเดšเตผ เดฌเตเดฐเดพเดžเตเดšเตเด•เตพ เด‡เดฒเตเดฒเดพเดคเดพเด•เตเด•เตเดจเตเดจเดคเต เดตเตเดฏเด•เตเดคเดฎเดฒเตเดฒ.

  2. เดตเต†เดฌเตโ€Œเดนเตเด•เตเด•เตเด•เตพ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเดจเตเดจเต (เด‰เดฆเดพเดนเดฐเดฃเด‚).

    • เด‡เดคเต เดจเดฟเด™เตเด™เดณเตเดŸเต† เดธเดฎเต€เดชเดจเดฎเดพเดฏเดฟเดฐเดฟเด•เตเด•เดฟเดฒเตเดฒ. เด‰เดฆเดพเดนเดฐเดฃเดคเตเดคเดฟเดจเต, เด‡เตป เดœเต†เด™เตเด•เดฟเตปเดธเต, เด’เดฐเต เดคเดฐเด‚ เดชเตˆเดชเตเดชเตเดฒเตˆเตป เดฎเดพเดคเตเดฐเดฎเต‡ เด…เดคเดฟเดจเตเดฑเต† เด•เต‹เตบเดซเดฟเด—เดฑเต‡เดทเดจเตเด•เตพ เดธเต‹เดดเตเดธเต เด•เต‹เดกเดฟเตฝ เดธเด‚เดฐเด•เตเดทเดฟเด•เตเด•เดพเดจเตเดณเตเดณ เด•เดดเดฟเดตเดฟเดจเต† เดชเดฟเดจเตเดคเตเดฃเดฏเตเด•เตเด•เต‚. เดตเต†เดฌเตโ€Œเดนเตเด•เตเด•เตเด•เตพ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเดฎเตเดชเต‹เตพ, เด…เดต เดชเตเดฐเต‹เดธเดธเตเดธเต เดšเต†เดฏเตเดฏเตเดจเตเดจเดคเดฟเดจเต เดจเดฟเด™เตเด™เดณเตเดŸเต‡เดคเดพเดฏ เดธเตโ€Œเด•เตเดฐเดฟเดชเตเดฑเตเดฑเต เดŽเดดเตเดคเต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต. เดˆ เดธเตเด•เตเดฐเดฟเดชเตเดฑเตเดฑเต เดœเต†เด™เตเด•เดฟเตปเดธเต เด‡เดจเตเดฑเตผเดซเต‡เดธเดฟเตฝ เดธเตเดฅเดพเดชเดฟเด•เตเด•เต‡เดฃเตเดŸเดคเตเดฃเตเดŸเต, เด…เดคเต เดชเดฐเดฟเดชเดพเดฒเดฟเด•เตเด•เดพเตป เดชเตเดฐเดฏเดพเดธเดฎเดพเดฃเต.

  3. เดŽเดดเตเดคเดพเตป เด•เตเดฐเต‹เตบเดœเต‹เดฌเต เด’เดฐเต เด•เตเดฌเตผเดจเต†เดฑเตเดฑเดธเต เด•เตเดฒเดธเตเดฑเตเดฑเตผ เดšเต‡เตผเด•เตเด•เตเด•.

    • เดŽเดดเตเดคเตเดคเดฟเดจเตเด‚ เดชเดฟเดจเตเดคเตเดฃเด•เตเด•เตเดฎเดพเดฏเดฟ เดธเดฎเดฏเด‚ เดšเต†เดฒเดตเดดเดฟเด•เตเด•เตเดจเตเดจเต.
    • เด“เดชเตเดชเดฑเต‡เดฑเตเดฑเตผ เด‡เดคเดฟเดจเด•เด‚ เดธเดฎเดพเดจเดฎเดพเดฏ เดถเตˆเดฒเดฟเดฏเดฟเตฝ เดชเตเดฐเดตเตผเดคเตเดคเดฟเด•เตเด•เตเดจเตเดจเต, เดฐเต‡เด–เดชเตเดชเต†เดŸเตเดคเตเดคเตเด•เดฏเตเด‚ เดชเดฟเดจเตเดคเตเดฃเดฏเตเด•เตเด•เตเด•เดฏเตเด‚ เดšเต†เดฏเตเดฏเตเดจเตเดจเต.

เดฒเต‡เด–เดจเดคเตเดคเดฟเตฝ เดจเดฟเด™เตเด™เดณเตเดŸเต† เดถเตเดฐเดฆเตเดงเดฏเตเด•เตเด•เต เดจเดจเตเดฆเดฟ. Github-เดฒเต† เดชเตเดฐเต‹เดœเด•เตเดฑเตเดฑเดฟเดฒเต‡เด•เตเด•เตเดณเตเดณ เดฒเดฟเด™เตเด•เต.

เด…เดตเดฒเด‚เดฌเด‚: www.habr.com

เด’เดฐเต เด…เดญเดฟเดชเตเดฐเดพเดฏเด‚ เดšเต‡เตผเด•เตเด•เตเด•