เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

เจ‡เจน เจฒเฉ‡เจ– เจœเจพเจตเจพ เจกเจฟเจตเฉˆเจฒเจชเจฐเจพเจ‚ เจฒเจˆ เจคเจฟเจ†เจฐ เจ•เฉ€เจคเจพ เจ—เจฟเจ† เจนเฉˆ เจœเจฟเจจเฉเจนเจพเจ‚ เจจเฉ‚เฉฐ GitLab เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ เจธเฉ‹เจจเจพเจŸเจพเจˆเจช เจ…เจคเฉ‡/เจœเจพเจ‚ เจฎเฉ‡เจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€เจ†เจ‚ เจตเจฟเฉฑเจš เจ†เจชเจฃเฉ‡ เจ‰เจคเจชเจพเจฆเจพเจ‚ เจจเฉ‚เฉฐ เจœเจฒเจฆเฉ€ เจชเฉเจฐเจ•เจพเจธเจผเจฟเจค เจ•เจฐเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆเฅค เจ‡เจธ เจฒเฉ‡เจ– เจตเจฟเฉฑเจš เจฎเฉˆเจ‚ เจ‡เจธ เจธเจฎเฉฑเจธเจฟเจ† เจจเฉ‚เฉฐ เจนเฉฑเจฒ เจ•เจฐเจจ เจฒเจˆ gitlab-runner, gitlab-ci เจ…เจคเฉ‡ maven-plugin เจธเจฅเจพเจชเจค เจ•เจฐเจจ เจฌเจพเจฐเฉ‡ เจ—เฉฑเจฒ เจ•เจฐเจพเจ‚เจ—เจพเฅค

เจœเจผเจฐเฉ‚เจฐเฉ€ เจธเจผเจฐเจคเจพเจ‚:

  • mvn เจ…เจคเฉ‡ GPG เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจฆเฉ€ เจธเฉเจฐเฉฑเจ–เจฟเจ…เจค เจธเจŸเฉ‹เจฐเฉ‡เจœเฅค
  • เจœเจจเจคเจ• CI เจ•เจพเจฐเจœเจพเจ‚ เจฆเจพ เจธเฉเจฐเฉฑเจ–เจฟเจ…เจค เจเจ—เจœเจผเฉ€เจ•เจฟเจŠเจธเจผเจจเฅค
  • เจœเจจเจคเจ• เจญเฉฐเจกเจพเจฐเจพเจ‚ เจตเจฟเฉฑเจš เจ•เจฒเจพเจคเจฎเจ• เจšเฉ€เจœเจผเจพเจ‚ (เจฐเจฟเจฒเฉ€เจœเจผ/เจธเจจเฉˆเจชเจธเจผเจพเจŸ) เจ…เฉฑเจชเจฒเฉ‹เจก เจ•เจฐเจจเจพเฅค
  • เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ เจตเจฟเฉฑเจš เจชเฉเจฐเจ•เจพเจธเจผเจจ เจฒเจˆ เจฐเฉ€เจฒเฉ€เจœเจผ เจธเฉฐเจธเจ•เจฐเจฃเจพเจ‚ เจฆเฉ€ เจ†เจŸเฉ‹เจฎเฉˆเจŸเจฟเจ• เจœเจพเจ‚เจšเฅค
  • เจฎเจฒเจŸเฉ€เจชเจฒ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸเจพเจ‚ เจฒเจˆ เจ‡เฉฑเจ• เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจตเจฟเฉฑเจš เจ•เจฒเจพเจคเจฎเจ• เจšเฉ€เจœเจผเจพเจ‚ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ เจ‡เฉฑเจ• เจ†เจฎ เจนเฉฑเจฒเฅค
  • เจธเจพเจฆเจ—เฉ€ เจ…เจคเฉ‡ เจตเจฐเจคเฉ‹เจ‚ เจตเจฟเฉฑเจš เจ†เจธเจพเจจเฉ€.

เจธเจฎเฉฑเจ—เจฐเฉ€

เจ†เจฎ เจœเจพเจฃเจ•เจพเจฐเฉ€

  • เจธเฉ‹เจจเจพเจŸเจพเจˆเจช เจ“เจเจธเจเจธ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจนเฉ‹เจธเจŸเจฟเฉฐเจ— เจธเฉ‡เจตเจพ เจฆเฉเจ†เจฐเจพ เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ เจตเจฟเฉฑเจš เจ•เจฒเจพเจ•เฉเจฐเจฟเจคเฉ€เจ†เจ‚ เจจเฉ‚เฉฐ เจชเฉเจฐเจ•เจพเจธเจผเจฟเจค เจ•เจฐเจจ เจฒเจˆ เจตเจฟเจงเฉ€ เจฆเจพ เจตเจฟเจธเจคเฉเจฐเจฟเจค เจตเจฐเจฃเจจ เจชเจนเจฟเจฒเจพเจ‚ เจนเฉ€ เจตเจฟเฉฑเจš เจฆเฉฑเจธเจฟเจ† เจ—เจฟเจ† เจนเฉˆเฅค เจ‡เจน เจฒเฉ‡เจ– เจ‰เจชเจญเฉ‹เจ—เจคเจพ Googolplex, เจ‡เจธ เจฒเจˆ เจฎเฉˆเจ‚ เจ‡เจธ เจฒเฉ‡เจ– เจฆเจพ เจธเจนเฉ€ เจธเจฅเจพเจจเจพเจ‚ 'เจคเฉ‡ เจนเจตเจพเจฒเจพ เจฆเฉ‡เจตเจพเจ‚เจ—เจพเฅค
  • เจฒเจˆ เจชเฉเจฐเฉ€-เจฐเจœเจฟเจธเจŸเจฐ เจ•เจฐเฉ‹ เจธเฉ‹เจจเจพเจŸเจพเจˆเจช เจœเฉ€เจฐเจพ เจ…เจคเฉ‡ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจ–เฉ‹เจฒเฉเจนเจฃ เจฒเจˆ เจ‡เฉฑเจ• เจŸเจฟเจ•เจŸ เจ–เฉ‹เจฒเฉเจนเฉ‹ (เจตเจงเฉ‡เจฐเฉ‡ เจตเฉ‡เจฐเจตเจฟเจ†เจ‚ เจฒเจˆ เจญเจพเจ— เจชเฉœเฉเจนเฉ‹ เจธเฉ‹เจจเจพเจŸเจพเจˆเจช เจœเฉ€เจฐเจพ 'เจคเฉ‡ เจŸเจฟเจ•เจŸ เจฌเจฃเจพเจ“). เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจ–เฉ‹เจฒเฉเจนเจฃ เจคเฉ‹เจ‚ เจฌเจพเจ…เจฆ, JIRA เจคเฉ‹เจ‚ เจฒเฉŒเจ—เจ‡เจจ/เจชเจพเจธเจตเจฐเจก เจœเฉ‹เฉœเจพ (เจ‡เจธ เจคเฉ‹เจ‚ เจฌเจพเจ…เจฆ เจธเฉ‹เจจเจพเจŸเจพเจˆเจช เจ–เจพเจคเฉ‡ เจตเจœเฉ‹เจ‚ เจœเจพเจฃเจฟเจ† เจœเจพเจ‚เจฆเจพ เจนเฉˆ) เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจธเฉ‹เจจเจพเจŸเจพเจˆเจช เจ—เจ เจœเฉ‹เฉœ 'เจคเฉ‡ เจ•เจฒเจพเจ•เฉเจฐเจฟเจคเฉ€เจ†เจ‚ เจจเฉ‚เฉฐ เจ…เฉฑเจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ เจ•เฉ€เจคเฉ€ เจœเจพเจตเฉ‡เจ—เฉ€เฅค
  • เจ…เฉฑเจ—เฉ‡, เจ‡เฉฑเจ• GPG เจ•เฉเฉฐเจœเฉ€ เจฌเจฃเจพเจ‰เจฃ เจฆเฉ€ เจชเฉเจฐเจ•เจฟเจฐเจฟเจ† เจจเฉ‚เฉฐ เจฌเจนเฉเจค เจ–เฉเจธเจผเจ• เจคเจฐเฉ€เจ•เฉ‡ เจจเจพเจฒ เจฆเฉฑเจธเจฟเจ† เจ—เจฟเจ† เจนเฉˆเฅค เจนเฉ‹เจฐ เจตเฉ‡เจฐเจตเจฟเจ†เจ‚ เจฒเจˆ เจธเฉˆเจ•เจธเจผเจจ เจฆเฉ‡เจ–เฉ‹ เจ†เจฐเจŸเฉ€เจซเฉˆเจ•เจŸเจพเจ‚ 'เจคเฉ‡ เจฆเจธเจคเจ–เจค เจ•เจฐเจจ เจฒเจˆ GnuPG เจฆเฉ€ เจธเฉฐเจฐเจšเจจเจพ เจ•เฉ€เจคเฉ€ เจœเจพ เจฐเจนเฉ€ เจนเฉˆ
  • เจœเฉ‡เจ•เจฐ เจคเฉเจธเฉ€เจ‚ เจ‡เฉฑเจ• GPG เจ•เฉเฉฐเจœเฉ€ (gnupg/gnupg2) เจฌเจฃเจพเจ‰เจฃ เจฒเจˆ เจฒเฉ€เจจเจ•เจธ เจ•เฉฐเจธเฉ‹เจฒ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเฉ‡ เจนเฉ‹, เจคเจพเจ‚ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจ‡เฉฐเจธเจŸเจพเจฒ เจ•เจฐเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆเฅค rng- เจธเฉฐเจฆ เจเจจเจŸเฉเจฐเฉ‹เจชเฉ€ เจฌเจฃเจพเจ‰เจฃ เจฒเจˆเฅค เจจเจนเฉ€เจ‚ เจคเจพเจ‚, เจ•เฉเฉฐเจœเฉ€ เจฌเจฃเจพเจ‰เจฃ เจตเจฟเฉฑเจš เจฌเจนเฉเจค เจฒเฉฐเจฎเจพ เจธเจฎเจพเจ‚ เจฒเฉฑเจ— เจธเจ•เจฆเจพ เจนเฉˆเฅค
  • เจธเจŸเฉ‹เจฐเฉ‡เจœ เจธเฉ‡เจตเจพเจตเจพเจ‚ เจœเจจเจคเจ• GPG เจ•เฉเฉฐเจœเฉ€เจ†เจ‚

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

GitLab เจตเจฟเฉฑเจš เจ‡เฉฑเจ• เจคเฉˆเจจเจพเจค เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจธเจฅเจพเจชเจค เจ•เจฐเจจเจพ

  • เจธเจญ เจคเฉ‹เจ‚ เจชเจนเจฟเจฒเจพเจ‚, เจคเฉเจนเจพเจจเฉ‚เฉฐ เจ‡เฉฑเจ• เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฌเจฃเจพเจ‰เจฃ เจ…เจคเฉ‡ เจ•เฉŒเจ‚เจซเจฟเจ—เจฐ เจ•เจฐเจจ เจฆเฉ€ เจœเจผเจฐเฉ‚เจฐเจค เจนเฉˆ เจœเจฟเจธ เจตเจฟเฉฑเจš เจชเจพเจˆเจชเจฒเจพเจˆเจจ เจจเฉ‚เฉฐ เจ†เจฐเจŸเฉ€เจซเฉˆเจ•เจŸเจพเจ‚ เจจเฉ‚เฉฐ เจคเฉˆเจจเจพเจค เจ•เจฐเจจ เจฒเจˆ เจธเจŸเฉ‹เจฐ เจ•เฉ€เจคเจพ เจœเจพเจตเฉ‡เจ—เจพเฅค เจฎเฉˆเจ‚ เจ†เจชเจฃเฉ‡ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฆเจพ เจจเจพเจฎ เจธเจงเจพเจฐเจจ เจ…เจคเฉ‡ เจ…เจธเฉฐเจญเจต เจคเฉŒเจฐ 'เจคเฉ‡ เจฐเฉฑเจ–เจฟเจ† เจนเฉˆ - เจตเฉฐเจกเฉ‹
  • เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจฌเจฃเจพเจ‰เจฃ เจคเฉ‹เจ‚ เจฌเจพเจ…เจฆ, เจคเฉเจนเจพเจจเฉ‚เฉฐ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจฌเจฆเจฒเจฃ เจฒเจˆ เจชเจนเฉเฉฐเจš เจจเฉ‚เฉฐ เจธเฉ€เจฎเจค เจ•เจฐเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆเฅค
    เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ -> เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ -> เจธเฉเจฐเฉฑเจ–เจฟเจ…เจค เจธเจผเจพเจ–เจพเจตเจพเจ‚ 'เจคเฉ‡ เจœเจพเจ“เฅค เจ…เจธเฉ€เจ‚ เจธเจพเจฐเฉ‡ เจจเจฟเจฏเจฎเจพเจ‚ เจจเฉ‚เฉฐ เจฎเจฟเจŸเจพเจ‰เจ‚เจฆเฉ‡ เจนเจพเจ‚ เจ…เจคเฉ‡ เจตเจพเจˆเจฒเจกเจ•เจพเจฐเจก * เจฆเฉ‡ เจจเจพเจฒ เจธเจฟเจฐเจซเจผ เจฎเฉ‡เจจเจŸเฉ‡เจจเจฐเจœเจผ เจฆเฉ€ เจญเฉ‚เจฎเจฟเจ•เจพ เจตเจพเจฒเฉ‡ เจ‰เจชเจญเฉ‹เจ—เจคเจพเจตเจพเจ‚ เจฒเจˆ เจงเฉฑเจ•เจฃ เจ…เจคเฉ‡ เจ…เจญเฉ‡เจฆ เจ•เจฐเจจ เจฆเฉ‡ เจ…เจงเจฟเจ•เจพเจฐ เจฆเฉ‡ เจจเจพเจฒ เจ‡เฉฑเจ• เจธเจฟเฉฐเจ—เจฒ เจจเจฟเจฏเจฎ เจœเฉ‹เฉœเจฆเฉ‡ เจนเจพเจ‚เฅค เจ‡เจน เจจเจฟเจฏเจฎ เจ‡เจธ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจ…เจคเฉ‡ เจธเจฎเฉ‚เจน เจฆเฉ‡ เจธเจพเจฐเฉ‡ เจ‰เจชเจญเฉ‹เจ—เจคเจพเจตเจพเจ‚ เจฒเจˆ เจ•เฉฐเจฎ เจ•เจฐเฉ‡เจ—เจพ เจœเจฟเจธ เจจเจพเจฒ เจ‡เจน เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจธเฉฐเจฌเฉฐเจงเจฟเจค เจนเฉˆเฅค
    เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ
  • เจœเฉ‡ เจ‡เฉฑเจฅเฉ‡ เจฌเจนเฉเจค เจธเจพเจฐเฉ‡ เจชเฉเจฐเจฌเฉฐเจงเจ• เจนเจจ, เจคเจพเจ‚ เจธเจญ เจคเฉ‹เจ‚ เจตเจงเฉ€เจ† เจนเฉฑเจฒ เจธเจฟเจงเจพเจ‚เจค เจตเจฟเฉฑเจš เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจคเฉฑเจ• เจชเจนเฉเฉฐเจš เจจเฉ‚เฉฐ เจธเฉ€เจฎเจค เจ•เจฐเจจเจพ เจนเฉ‹เจตเฉ‡เจ—เจพเฅค
    เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ -> เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> เจ†เจฎ -> เจฆเจฟเฉฑเจ–, เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจตเจฟเจธเจผเฉ‡เจธเจผเจคเจพเจตเจพเจ‚, เจ…เจจเฉเจฎเจคเฉ€เจ†เจ‚ 'เจคเฉ‡ เจœเจพเจ“ เจ…เจคเฉ‡ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฆเฉ€ เจฆเจฟเฉฑเจ– เจจเฉ‚เฉฐ เจธเฉˆเฉฑเจŸ เจ•เจฐเฉ‹ เจชเฉเจฐเจพเจˆเจตเฉ‡เจŸ.
    เจฎเฉ‡เจฐเฉ‡ เจ•เฉ‹เจฒ เจ‡เฉฑเจ• เจœเจจเจคเจ• เจคเฉŒเจฐ 'เจคเฉ‡ เจชเจนเฉเฉฐเจšเจฏเฉ‹เจ— เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจนเฉˆ, เจ•เจฟเจ‰เจ‚เจ•เจฟ เจฎเฉˆเจ‚ เจ†เจชเจฃเฉ‡ เจ–เฉเจฆ เจฆเฉ‡ GitLab เจฐเจจเจฐ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเจพ เจนเจพเจ‚ เจ…เจคเฉ‡ เจธเจฟเจฐเจซ เจฎเฉ‡เจฐเฉ‡ เจ•เฉ‹เจฒ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจจเฉ‚เฉฐ เจฌเจฆเจฒเจฃ เจฆเฉ€ เจชเจนเฉเฉฐเจš เจนเฉˆเฅค เจ–เฉˆเจฐ, เจ…เจธเจฒ เจตเจฟเฉฑเจš, เจœเจจเจคเจ• เจชเจพเจˆเจชเจฒเจพเจˆเจจ เจฒเฉŒเจ—เจพเจ‚ เจตเจฟเฉฑเจš เจจเจฟเฉฑเจœเฉ€ เจœเจพเจฃเจ•เจพเจฐเฉ€ เจฆเจฟเจ–เจพเจ‰เจฃเจพ เจฎเฉ‡เจฐเฉ‡ เจนเจฟเฉฑเจค เจตเจฟเฉฑเจš เจจเจนเฉ€เจ‚ เจนเฉˆเฅค
  • เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจจเฉ‚เฉฐ เจฌเจฆเจฒเจฃ เจฒเจˆ เจจเจฟเจฏเจฎเจพเจ‚ เจจเฉ‚เฉฐ เจธเจ–เจผเจค เจ•เจฐเจจเจพ
    เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ -> เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ -> เจชเฉเจธเจผ เจจเจฟเจฏเจฎ 'เจคเฉ‡ เจœเจพเจ“ เจ…เจคเฉ‡ เจ•เจฎเจŸเจฐ เจชเจพเจฌเฉฐเจฆเฉ€ เจธเฉˆเจŸ เจ•เจฐเฉ‹, เจœเจพเจ‚เจš เจ•เจฐเฉ‹ เจ•เจฟ เจ•เฉ€ เจฒเฉ‡เจ–เจ• เจ—เจฟเฉฑเจŸเจฒเฉˆเจฌ เจ‰เจชเจญเฉ‹เจ—เจคเจพ เจซเจฒเฉˆเจ— เจนเฉˆเฅค เจฎเฉˆเจ‚ เจธเจฅเจพเจชเจค เจ•เจฐเจจ เจฆเฉ€ เจตเฉ€ เจธเจฟเจซเจพเจฐเจธเจผ เจ•เจฐเจฆเจพ เจนเจพเจ‚ เจตเจšเจจเจฌเฉฑเจง เจฆเจธเจคเจ–เจค, เจ…เจคเฉ‡ เจ…เจธเจตเฉ€เจ•เจพเจฐเจฟเจค เจ•เจฎเจฟเจŸ เจซเจฒเฉˆเจ— เจธเฉˆเฉฑเจŸ เจ•เจฐเฉ‹เฅค
  • เจ…เฉฑเจ—เฉ‡ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจ•เจพเจฐเจœเจพเจ‚ เจจเฉ‚เฉฐ เจธเจผเฉเจฐเฉ‚ เจ•เจฐเจจ เจฒเจˆ เจ‡เฉฑเจ• เจŸเจฐเจฟเฉฑเจ—เจฐ เจจเฉ‚เฉฐ เจ•เฉŒเจ‚เจซเจฟเจ—เจฐ เจ•เจฐเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ
    เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ -> เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> CI / CD -> เจชเจพเจˆเจชเจฒเจพเจˆเจจ เจŸเจฐเจฟเจ—เจฐ 'เจคเฉ‡ เจœเจพเจ“ เจ…เจคเฉ‡ เจ‡เฉฑเจ• เจจเจตเจพเจ‚ เจŸเจฐเจฟเฉฑเจ—เจฐ-เจŸเฉ‹เจ•เจจ เจฌเจฃเจพเจ“
    เจ‡เจธ เจŸเฉ‹เจ•เจจ เจจเฉ‚เฉฐ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸเจพเจ‚ เจฆเฉ‡ เจธเจฎเฉ‚เจน เจฒเจˆ เจตเฉ‡เจฐเฉ€เจเจฌเจฒเจพเจ‚ เจฆเฉ€ เจ†เจฎ เจธเฉฐเจฐเจšเจจเจพ เจตเจฟเฉฑเจš เจคเฉเจฐเฉฐเจค เจœเฉ‹เฉœเจฟเจ† เจœเจพ เจธเจ•เจฆเจพ เจนเฉˆเฅค
    เจ—เจฐเฉเฉฑเจช -> เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> CI / CD -> เจตเฉ‡เจฐเฉ€เจเจฌเจฒ 'เจคเฉ‡ เจœเจพเจ“ เจ…เจคเฉ‡ เจ‡เฉฑเจ• เจตเฉ‡เจฐเฉ€เจเจฌเจฒ เจœเฉ‹เฉœเฉ‹ DEPLOY_TOKEN เจฎเฉเฉฑเจฒ เจตเจฟเฉฑเจš เจŸเจฐเจฟเฉฑเจ—เจฐ-เจŸเฉ‹เจ•เจจ เจฆเฉ‡ เจจเจพเจฒเฅค

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

GitLab เจฆเฉŒเฉœเจพเจ•

เจ‡เจน เจญเจพเจ— เจคเฉเจนเจพเจกเฉ‡ เจ†เจชเจฃเฉ‡ (เจ–เจพเจธ) เจ…เจคเฉ‡ เจœเจจเจคเจ• (เจธเจผเฉ‡เจ…เจฐเจก) เจฐเจจเจฐ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจ•เฉ‡ เจคเฉˆเจจเจพเจค เจ•เจฐเจจ เจฒเจˆ เจ•เจพเจฐเจœเจพเจ‚ เจจเฉ‚เฉฐ เจšเจฒเจพเจ‰เจฃ เจฒเจˆ เจธเฉฐเจฐเจšเจจเจพ เจฆเจพ เจตเจฐเจฃเจจ เจ•เจฐเจฆเจพ เจนเฉˆเฅค

เจ–เจพเจธ เจฆเฉŒเฉœเจพเจ•

เจฎเฉˆเจ‚ เจ†เจชเจฃเฉ‡ เจ–เฉเจฆ เจฆเฉ‡ เจฆเฉŒเฉœเจพเจ•เจพเจ‚ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเจพ เจนเจพเจ‚ เจ•เจฟเจ‰เจ‚เจ•เจฟ, เจธเจญ เจคเฉ‹เจ‚ เจชเจนเจฟเจฒเจพเจ‚, เจ‡เจน เจธเฉเจตเจฟเจงเจพเจœเจจเจ•, เจคเฉ‡เจœเจผ เจ…เจคเฉ‡ เจธเจธเจคเจพ เจนเฉˆ.
เจ‡เฉฑเจ• เจฆเฉŒเฉœเจพเจ• เจฒเจˆ, เจฎเฉˆเจ‚ 1 CPU, 2 GB RAM, 20 GB HDD เจฆเฉ‡ เจจเจพเจฒ เจ‡เฉฑเจ• Linux VDS เจฆเฉ€ เจธเจฟเจซเจผเจพเจฐเจธเจผ เจ•เจฐเจฆเจพ เจนเจพเจ‚เฅค เจœเจพเจฐเฉ€ เจ•เจฐเจจ เจฆเฉ€ เจ•เฉ€เจฎเจค ~3000โ‚ฝ เจชเฉเจฐเจคเฉ€ เจธเจพเจฒ เจนเฉˆเฅค

เจฎเฉ‡เจฐเจพ เจฆเฉŒเฉœเจพเจ•

เจฆเฉŒเฉœเจพเจ• เจฒเจˆ เจฎเฉˆเจ‚ VDS 4 CPU, 4 GB RAM, 50 GB SSD เจฒเจฟเจ†เฅค เจฒเจพเจ—เจค ~11000โ‚ฝ เจ…เจคเฉ‡ เจ‡เจธ 'เจคเฉ‡ เจ•เจฆเฉ‡ เจชเจ›เจคเจพเจตเจพ เจจเจนเฉ€เจ‚ เจนเฉ‹เจ‡เจ†เฅค
เจฎเฉ‡เจฐเฉ‡ เจ•เฉ‹เจฒ เจ•เฉเฉฑเจฒ 7 เจฎเจธเจผเฉ€เจจเจพเจ‚ เจนเจจเฅค 5 เจ…เจฐเฉ‚เจฌเจพ 'เจคเฉ‡ เจ…เจคเฉ‡ 2 เจ†เจˆเจนเฉ‹เจฐ 'เจคเฉ‡เฅค

เจ‡เจธ เจฒเจˆ เจธเจพเจกเฉ‡ เจ•เฉ‹เจฒ เจ‡เฉฑเจ• เจฆเฉŒเฉœเจพเจ• เจนเฉˆ. เจนเฉเจฃ เจ…เจธเฉ€เจ‚ เจ‡เจธเจจเฉ‚เฉฐ เจ•เฉŒเจ‚เจซเจฟเจ—เจฐ เจ•เจฐเจพเจ‚เจ—เฉ‡เฅค
เจ…เจธเฉ€เจ‚ SSH เจฐเจพเจนเฉ€เจ‚ เจฎเจธเจผเฉ€เจจ 'เจคเฉ‡ เจœเจพเจ‚เจฆเฉ‡ เจนเจพเจ‚ เจ…เจคเฉ‡ java, git, maven, gnupg2 เจจเฉ‚เฉฐ เจ‡เฉฐเจธเจŸเจพเจฒ เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚เฅค

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

เจ—เจฟเจŸเจฒเฉˆเจฌ เจฐเจจเจฐ เจธเจฅเจพเจชเจค เจ•เจฐเจจเจพ

  • เจ‡เฉฑเจ• เจจเจตเจพเจ‚ เจธเจฎเฉ‚เจน เจฌเจฃเจพเจ“ runner
    sudo groupadd runner
  • เจฎเฉˆเจตเฉ‡เจจ เจ•เฉˆเจธเจผ เจฒเจˆ เจ‡เฉฑเจ• เจกเจพเจ‡เจฐเฉˆเจ•เจŸเจฐเฉ€ เจฌเจฃเจพเจ“ เจ…เจคเฉ‡ เจธเจฎเฉ‚เจน เจ…เจจเฉเจฎเจคเฉ€เจ†เจ‚ เจจเจฟเจฐเจงเจพเจฐเจค เจ•เจฐเฉ‹ runner
    เจคเฉเจธเฉ€เจ‚ เจ‡เจธ เจฌเจฟเฉฐเจฆเฉ‚ เจจเฉ‚เฉฐ เจ›เฉฑเจก เจธเจ•เจฆเฉ‡ เจนเฉ‹ เจœเฉ‡เจ•เจฐ เจคเฉเจธเฉ€เจ‚ เจ‡เฉฑเจ• เจฎเจธเจผเฉ€เจจ 'เจคเฉ‡ เจ•เจˆ เจฆเฉŒเฉœเจพเจ•เจพเจ‚ เจจเฉ‚เฉฐ เจšเจฒเจพเจ‰เจฃ เจฆเฉ€ เจฏเฉ‹เจœเจจเจพ เจจเจนเฉ€เจ‚ เจฌเจฃเจพเจ‰เจ‚เจฆเฉ‡ เจนเฉ‹เฅค

    mkdir -p /usr/cache/.m2/repository
    chown -R :runner /usr/cache
    chmod -R 770 /usr/cache
  • เจ‡เฉฑเจ• เจ‰เจชเจญเฉ‹เจ—เจคเจพ เจฌเจฃเจพเจ“ gitlab-deployer เจ…เจคเฉ‡ เจ—เจฐเฉเฉฑเจช เจตเจฟเฉฑเจš เจธเจผเจพเจฎเจฒ เจ•เจฐเฉ‹ runner
    useradd -m -d /home/gitlab-deployer gitlab-deployer
    usermod -a -G runner gitlab-deployer
  • เจซเจพเจˆเจฒ เจตเจฟเฉฑเจš เจธเจผเจพเจฎเจฒ เจ•เจฐเฉ‹ /etc/ssh/sshd_config เจ…เจ—เจฒเฉ€ เจฒเจพเจˆเจจ
    AllowUsers root@* [email protected]
  • เจฎเฉเฉœ - เจšเจพเจฒเฉ‚ sshd
    systemctl restart sshd
  • เจ‰เจชเจญเฉ‹เจ—เจคเจพ เจฒเจˆ เจ‡เฉฑเจ• เจชเจพเจธเจตเจฐเจก เจธเฉˆเฉฑเจŸ เจ•เจฐเจจเจพ gitlab-deployer (เจธเจงเจพเจฐเจจ เจนเฉ‹ เจธเจ•เจฆเจพ เจนเฉˆ, เจ•เจฟเจ‰เจ‚เจ•เจฟ เจฒเฉ‹เจ•เจฒเจนเฉ‹เจธเจŸ เจฒเจˆ เจ‡เฉฑเจ• เจชเจพเจฌเฉฐเจฆเฉ€ เจนเฉˆ)
    passwd gitlab-deployer
  • GitLab เจฐเจจเจฐ (Linux x86-64) เจจเฉ‚เฉฐ เจธเจฅเจพเจชเจฟเจค เจ•เจฐเฉ‹
    sudo wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
    sudo chmod +x /usr/local/bin/gitlab-runner
    ln -s /usr/local/bin/gitlab-runner /etc/alternatives/gitlab-runner
    ln -s /etc/alternatives/gitlab-runner /usr/bin/gitlab-runner
  • เจตเฉˆเฉฑเจฌเจธเจพเจˆเจŸ gitlab.com -> deploy-project -> Settings -> CI/CD -> เจฐเจจเจฐ -> เจ–เจพเจธ เจฆเฉŒเฉœเจพเจ• 'เจคเฉ‡ เจœเจพเจ“ เจ…เจคเฉ‡ เจฐเจœเจฟเจธเจŸเฉเจฐเฉ‡เจธเจผเจจ เจŸเฉ‹เจ•เจจ เจฆเฉ€ เจ•เจพเจชเฉ€ เจ•เจฐเฉ‹เฅค

เจธเจ•เจฐเฉ€เจจ

เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

  • เจ‡เฉฑเจ• เจฆเฉŒเฉœเจพเจ• เจจเฉ‚เฉฐ เจฐเจœเจฟเจธเจŸเจฐ เจ•เจฐเจจเจพ
    gitlab-runner register --config /etc/gitlab-runner/gitlab-deployer-config.toml

เจ•เจพเจฐเจœ เจจเฉ‚เฉฐ

Runtime platform arch=amd64 os=linux pid=17594 revision=3001a600 version=11.10.0
Running in system-mode.
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://gitlab.com/
Please enter the gitlab-ci token for this runner:
REGISTRATION_TOKEN
Please enter the gitlab-ci description for this runner:
[ih1174328.vds.myihor.ru]: Deploy Runner
Please enter the gitlab-ci tags for this runner (comma separated):
deploy
Registering runner... succeeded                     runner=ZvKdjJhx
Please enter the executor: docker-ssh, parallels, virtualbox, docker-ssh+machine, kubernetes, docker, ssh, docker+machine, shell:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

  • เจ…เจธเฉ€เจ‚ เจœเจพเจ‚เจš เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚ เจ•เจฟ เจฆเฉŒเฉœเจพเจ• เจฐเจœเจฟเจธเจŸเจฐเจก เจนเฉˆเฅค เจตเฉˆเฉฑเจฌเจธเจพเจˆเจŸ gitlab.com 'เจคเฉ‡ เจœเจพเจ“ -> deploy-project -> Settings -> CI/CD -> เจฆเฉŒเฉœเจพเจ• -> เจ–เจพเจธ เจฆเฉŒเฉœเจพเจ• -> เจฆเฉŒเฉœเจพเจ• เจ‡เจธ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฒเจˆ เจ•เจฟเจฐเจฟเจ†เจธเจผเฉ€เจฒ เจนเจจเฅค

เจธเจ•เจฐเฉ€เจจ

เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

  • เจธเจผเจพเจฎเจฒ เจ•เจฐเฉ‹ เจตเฉฑเจ–เจฐเจพ เจธเฉ‡เจตเจพ /etc/systemd/system/gitlab-deployer.service
    [Unit]
    Description=GitLab Deploy Runner
    After=syslog.target network.target
    ConditionFileIsExecutable=/usr/local/bin/gitlab-runner
    [Service]
    StartLimitInterval=5
    StartLimitBurst=10
    ExecStart=/usr/local/bin/gitlab-runner "run" "--working-directory" "/home/gitlab-deployer" "--config" "/etc/gitlab-runner/gitlab-deployer-config.toml" "--service" "gitlab-deployer" "--syslog" "--user" "gitlab-deployer"
    Restart=always
    RestartSec=120
    [Install]
    WantedBy=multi-user.target
  • เจ†เจ“ เจธเฉ‡เจตเจพ เจธเจผเฉเจฐเฉ‚ เจ•เจฐเฉ€เจเฅค
    systemctl enable gitlab-deployer.service
    systemctl start gitlab-deployer.service
    systemctl status gitlab-deployer.service
  • เจ…เจธเฉ€เจ‚ เจœเจพเจ‚เจš เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚ เจ•เจฟ เจฆเฉŒเฉœเจพเจ• เจšเฉฑเจฒ เจฐเจฟเจนเจพ เจนเฉˆเฅค

เจ‰เจฆเจพเจนเจฐเจจ:

เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

GPG เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจคเจฟเจ†เจฐ เจ•เฉ€เจคเฉ€เจ†เจ‚ เจœเจพ เจฐเจนเฉ€เจ†เจ‚ เจนเจจ

  • เจ‰เจธเฉ‡ เจฎเจธเจผเฉ€เจจ เจคเฉ‹เจ‚ เจ…เจธเฉ€เจ‚ เจ‰เจชเจญเฉ‹เจ—เจคเจพ เจฆเฉ‡ เจ…เจงเฉ€เจจ ssh เจฆเฉเจ†เจฐเจพ เจฒเฉŒเจ—เจ‡เจจ เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚ gitlab-deployer (เจ‡เจน GPG เจ•เฉเฉฐเจœเฉ€ เจฌเจฃเจพเจ‰เจฃ เจฒเจˆ เจฎเจนเฉฑเจคเจตเจชเฉ‚เจฐเจจ เจนเฉˆ)

    ssh [email protected]

  • เจ…เจธเฉ€เจ‚ เจธเจตเจพเจฒเจพเจ‚ เจฆเฉ‡ เจœเจตเจพเจฌ เจฆเฉ‡ เจ•เฉ‡ เจ‡เฉฑเจ• เจ•เฉเฉฐเจœเฉ€ เจคเจฟเจ†เจฐ เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚เฅค เจฎเฉˆเจ‚ เจ†เจชเจฃเจพ เจจเจพเจ‚ เจ…เจคเฉ‡ เจˆเจฎเฉ‡เจฒ เจตเจฐเจคเจฟเจ†เฅค
    เจ•เฉเฉฐเจœเฉ€ เจฒเจˆ เจชเจพเจธเจตเจฐเจก เจฆเฉ‡เจฃเจพ เจฏเจ•เฉ€เจจเฉ€ เจฌเจฃเจพเจ“เฅค เจ‡เจธ เจ•เฉเฉฐเจœเฉ€ เจจเจพเจฒ เจ•เจฒเจพเจคเจฎเจ• เจšเฉ€เจœเจผเจพเจ‚ 'เจคเฉ‡ เจฆเจธเจคเจ–เจค เจ•เฉ€เจคเฉ‡ เจœเจพเจฃเจ—เฉ‡เฅค

    gpg --gen-key 

  • เจšเฉˆเฉฑเจ• เจ•เจฐเฉ‹

    gpg --list-keys -a
    /home/gitlab-deployer/.gnupg/pubring.gpg
    ----------------------------------------
    pub   4096R/00000000 2019-04-19
    uid                  Petruha Petrov <[email protected]>
    sub   4096R/11111111 2019-04-19

  • เจธเจพเจกเฉ€ เจœเจจเจคเจ• เจ•เฉเฉฐเจœเฉ€ เจจเฉ‚เฉฐ เจ•เฉเฉฐเจœเฉ€ เจธเจฐเจตเจฐ 'เจคเฉ‡ เจ…เฉฑเจชเจฒเฉ‹เจก เจ•เจฐเจจเจพ

    gpg --keyserver keys.gnupg.net --send-key 00000000
    gpg: sending key 00000000 to hkp server keys.gnupg.net

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

Maven เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เฉ€เจคเฉ€ เจœเจพ เจฐเจนเฉ€ เจนเฉˆ

  • เจ‰เจชเจญเฉ‹เจ—เจคเจพ เจตเจœเฉ‹เจ‚ เจฒเฉŒเจ—เจ‡เจจ เจ•เจฐเฉ‹ gitlab-deployer
    su gitlab-deployer 
  • เจ‡เฉฑเจ• เจฎเจพเจตเฉ‡เจจ เจกเจพเจ‡เจฐเฉˆเจ•เจŸเจฐเฉ€ เจฌเจฃเจพเจ“ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจ…เจคเฉ‡ เจ•เฉˆเจธเจผ เจจเจพเจฒ เจฒเจฟเฉฐเจ• เจ•เจฐเฉ‹ (เจ•เฉ‹เจˆ เจ—เจฒเจคเฉ€ เจจเจพ เจ•เจฐเฉ‹)
    เจคเฉเจธเฉ€เจ‚ เจ‡เจธ เจฌเจฟเฉฐเจฆเฉ‚ เจจเฉ‚เฉฐ เจ›เฉฑเจก เจธเจ•เจฆเฉ‡ เจนเฉ‹ เจœเฉ‡เจ•เจฐ เจคเฉเจธเฉ€เจ‚ เจ‡เฉฑเจ• เจฎเจธเจผเฉ€เจจ 'เจคเฉ‡ เจ•เจˆ เจฆเฉŒเฉœเจพเจ•เจพเจ‚ เจจเฉ‚เฉฐ เจšเจฒเจพเจ‰เจฃ เจฆเฉ€ เจฏเฉ‹เจœเจจเจพ เจจเจนเฉ€เจ‚ เจฌเจฃเจพเจ‰เจ‚เจฆเฉ‡ เจนเฉ‹เฅค

    mkdir -p ~/.m2/repository
    ln -s /usr/cache/.m2/repository /home/gitlab-deployer/.m2/repository
  • เจ‡เฉฑเจ• เจฎเจพเจธเจŸเจฐ เจ•เฉเฉฐเจœเฉ€ เจฌเจฃเจพเจ“
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}
  • เจ‡เฉฑเจ• เจซเจผเจพเจˆเจฒ เจฌเจฃเจพเจ“ ~/.m2/settings-security.xml
    <settingsSecurity>
    <master>{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}</master>
    </settingsSecurity>
  • เจธเฉ‹เจจเจพเจŸเจพเจˆเจช เจ–เจพเจคเฉ‡ เจฒเจˆ เจชเจพเจธเจตเจฐเจก เจเจจเจ•เฉเจฐเจฟเจชเจŸ เจ•เจฐเจจเจพ
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • เจ‡เฉฑเจ• เจซเจผเจพเจˆเจฒ เจฌเจฃเจพเจ“ ~/.m2/settings.xml
    <settings>  
    <profiles>
        <profile>
            <id>env</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <gpg.passphrase>GPG_SECRET_KEY_PASSPHRASE</gpg.passphrase>
            </properties>
        </profile>
    </profiles>
    <servers>
        <server>
            <id>sonatype</id>
            <username>SONATYPE_USERNAME</username>
            <password>{98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}</password>
        </server>
    </servers>
    </settings>

เจ•เจฟเฉฑเจฅเฉ‡,
GPG_SECRET_KEY_PASSPHRASE - GPG เจ•เฉเฉฐเจœเฉ€ เจฒเจˆ เจชเจพเจธเจตเจฐเจก
SONATYPE_USERNAME โ€” sonatype เจ–เจพเจคเจพ เจฒเฉŒเจ—เจ‡เจจ

เจ‡เจน เจฆเฉŒเฉœเจพเจ• เจฆเฉ‡ เจธเฉˆเฉฑเจŸเจ…เฉฑเจช เจจเฉ‚เฉฐ เจชเฉ‚เจฐเจพ เจ•เจฐเจฆเจพ เจนเฉˆ, เจคเฉเจธเฉ€เจ‚ เจธเฉˆเจ•เจธเจผเจจ 'เจคเฉ‡ เจœเจพ เจธเจ•เจฆเฉ‡ เจนเฉ‹ เจ—เจฟเฉฑเจŸเจฒเจพเจฌ เจธเฉ€.เจ†เจˆ.

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

เจธเจพเจ‚เจเจพ เจฆเฉŒเฉœเจพเจ•

GPG เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจคเจฟเจ†เจฐ เจ•เฉ€เจคเฉ€เจ†เจ‚ เจœเจพ เจฐเจนเฉ€เจ†เจ‚ เจนเจจ

  • เจธเจญ เจคเฉ‹เจ‚ เจชเจนเจฟเจฒเจพเจ‚, เจคเฉเจนเจพเจจเฉ‚เฉฐ เจ‡เฉฑเจ• GPG เจ•เฉเฉฐเจœเฉ€ เจฌเจฃเจพเจ‰เจฃ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆเฅค เจ…เจœเจฟเจนเจพ เจ•เจฐเจจ เจฒเจˆ, gnupg เจ‡เฉฐเจธเจŸเจพเจฒ เจ•เจฐเฉ‹เฅค

    yum install -y gnupg

  • เจ…เจธเฉ€เจ‚ เจธเจตเจพเจฒเจพเจ‚ เจฆเฉ‡ เจœเจตเจพเจฌ เจฆเฉ‡ เจ•เฉ‡ เจ‡เฉฑเจ• เจ•เฉเฉฐเจœเฉ€ เจคเจฟเจ†เจฐ เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚เฅค เจฎเฉˆเจ‚ เจ†เจชเจฃเจพ เจจเจพเจ‚ เจ…เจคเฉ‡ เจˆเจฎเฉ‡เจฒ เจตเจฐเจคเจฟเจ†เฅค เจ•เฉเฉฐเจœเฉ€ เจฒเจˆ เจชเจพเจธเจตเจฐเจก เจฆเฉ‡เจฃเจพ เจฏเจ•เฉ€เจจเฉ€ เจฌเจฃเจพเจ“เฅค

    gpg --gen-key 

  • เจ•เฉเฉฐเจœเฉ€ 'เจคเฉ‡ เจœเจพเจฃเจ•เจพเจฐเฉ€ เจชเฉเจฐเจฆเจฐเจธเจผเจฟเจค เจ•เฉ€เจคเฉ€ เจœเจพ เจฐเจนเฉ€ เจนเฉˆ

    gpg --list-keys -a
    pub   rsa3072 2019-04-24 [SC] [expires: 2021-04-23]
      2D0D1706366FC4AEF79669E24D09C55BBA3FD728
    uid           [ultimate] tttemp <[email protected]>
    sub   rsa3072 2019-04-24 [E] [expires: none]

  • เจธเจพเจกเฉ€ เจœเจจเจคเจ• เจ•เฉเฉฐเจœเฉ€ เจจเฉ‚เฉฐ เจ•เฉเฉฐเจœเฉ€ เจธเจฐเจตเจฐ 'เจคเฉ‡ เจ…เฉฑเจชเจฒเฉ‹เจก เจ•เจฐเจจเจพ

    gpg --keyserver keys.gnupg.net --send-key 2D0D1706366FC4AEF79669E24D09C55BBA3FD728
    gpg: sending key 2D0D1706366FC4AEF79669E24D09C55BBA3FD728 to hkp server keys.gnupg.net

  • เจธเจพเจจเฉ‚เฉฐ เจชเฉเจฐเจพเจˆเจตเฉ‡เจŸ เจ•เฉเฉฐเจœเฉ€ เจฎเจฟเจฒเจฆเฉ€ เจนเฉˆ

    gpg --export-secret-keys --armor 2D0D1706366FC4AEF79669E24D09C55BBA3FD728
    -----BEGIN PGP PRIVATE KEY BLOCK-----
    lQWGBFzAqp8BDADN41CPwJ/gQwiKEbyA902DKw/WSB1AvZQvV/ZFV77xGeG4K7k5
    ...
    =2Wd2
    -----END PGP PRIVATE KEY BLOCK-----

  • เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> CI / CD -> เจตเฉ‡เจฐเฉ€เจเจฌเจฒ 'เจคเฉ‡ เจœเจพเจ“ เจ…เจคเฉ‡ เจ‡เฉฑเจ• เจตเฉ‡เจฐเฉ€เจเจฌเจฒ เจตเจฟเฉฑเจš เจชเฉเจฐเจพเจˆเจตเฉ‡เจŸ เจ•เฉเฉฐเจœเฉ€ เจจเฉ‚เฉฐ เจธเฉเจฐเฉฑเจ–เจฟเจ…เจค เจ•เจฐเฉ‹ GPG_SECRET_KEY
    เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

Maven เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เฉ€เจคเฉ€ เจœเจพ เจฐเจนเฉ€ เจนเฉˆ

  • เจ‡เฉฑเจ• เจฎเจพเจธเจŸเจฐ เจ•เฉเฉฐเจœเฉ€ เจฌเจฃเจพเจ“
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}
  • เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> CI / CD -> เจตเฉ‡เจฐเฉ€เจเจฌเจฒ 'เจคเฉ‡ เจœเจพเจ“ เจ…เจคเฉ‡ เจ‡เฉฑเจ• เจตเฉ‡เจฐเฉ€เจเจฌเจฒ เจตเจฟเฉฑเจš เจธเฉเจฐเฉฑเจ–เจฟเจ…เจค เจ•เจฐเฉ‹ SETTINGS_SECURITY_XML เจนเฉ‡เจ  เจฒเจฟเจ–เฉ€เจ†เจ‚ เจฒเจพเจˆเจจเจพเจ‚:
    <settingsSecurity>
    <master>{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}</master>
    </settingsSecurity>
  • เจธเฉ‹เจจเจพเจŸเจพเจˆเจช เจ–เจพเจคเฉ‡ เจฒเจˆ เจชเจพเจธเจตเจฐเจก เจเจจเจ•เฉเจฐเจฟเจชเจŸ เจ•เจฐเจจเจพ
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> เจธเฉˆเจŸเจฟเฉฐเจ—เจพเจ‚ -> CI / CD -> เจตเฉ‡เจฐเฉ€เจเจฌเจฒ 'เจคเฉ‡ เจœเจพเจ“ เจ…เจคเฉ‡ เจ‡เฉฑเจ• เจตเฉ‡เจฐเฉ€เจเจฌเจฒ เจตเจฟเฉฑเจš เจธเฉเจฐเฉฑเจ–เจฟเจ…เจค เจ•เจฐเฉ‹ SETTINGS_XML เจนเฉ‡เจ  เจฒเจฟเจ–เฉ€เจ†เจ‚ เจฒเจพเจˆเจจเจพเจ‚:
    <settings>  
    <profiles>
        <profile>
            <id>env</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <gpg.passphrase>GPG_SECRET_KEY_PASSPHRASE</gpg.passphrase>
            </properties>
        </profile>
    </profiles>
    <servers>
        <server>
            <id>sonatype</id>
            <username>sonatype_username</username>
            <password>{98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}</password>
        </server>
    </servers>
    </settings>

เจ•เจฟเฉฑเจฅเฉ‡,
GPG_SECRET_KEY_PASSPHRASE - GPG เจ•เฉเฉฐเจœเฉ€ เจฒเจˆ เจชเจพเจธเจตเจฐเจก
SONATYPE_USERNAME โ€” sonatype เจ–เจพเจคเจพ เจฒเฉŒเจ—เจ‡เจจ

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

เจกเฉŒเจ•เจฐ เจšเจฟเฉฑเจคเจฐ เจจเฉ‚เฉฐ เจฒเจพเจ—เฉ‚ เจ•เจฐเฉ‹

  • เจ…เจธเฉ€เจ‚ Java เจฆเฉ‡ เจฒเฉ‹เฉœเฉ€เจ‚เจฆเฉ‡ เจธเฉฐเจธเจ•เจฐเจฃ เจฆเฉ‡ เจจเจพเจฒ เจคเฉˆเจจเจพเจค เจ•เจพเจฐเจœเจพเจ‚ เจจเฉ‚เฉฐ เจšเจฒเจพเจ‰เจฃ เจฒเจˆ เจ‡เฉฑเจ• เจ•เจพเจซเจผเฉ€ เจธเจงเจพเจฐเจจ เจกเฉŒเจ•เจฐเจซเจพเจˆเจฒ เจฌเจฃเจพเจ‰เจ‚เจฆเฉ‡ เจนเจพเจ‚เฅค เจนเฉ‡เจ เจพเจ‚ เจ…เจฒเจชเจพเจˆเจจ เจฒเจˆ เจ‡เฉฑเจ• เจ‰เจฆเจพเจนเจฐเจจ เจนเฉˆ.

    FROM java:8u111-jdk-alpine
    RUN apk add gnupg maven git --update-cache 
    --repository http://dl-4.alpinelinux.org/alpine/edge/community/ --allow-untrusted && 
    mkdir ~/.m2/

  • เจคเฉเจนเจพเจกเฉ‡ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฒเจˆ เจ‡เฉฑเจ• เจ•เฉฐเจŸเฉ‡เจจเจฐ เจจเฉ‚เฉฐ เจ‡เจ•เฉฑเจ เจพ เจ•เจฐเจจเจพ

    docker build -t registry.gitlab.com/group/deploy .

  • เจ…เจธเฉ€เจ‚ เจฐเจœเจฟเจธเจŸเจฐเฉ€ เจตเจฟเฉฑเจš เจ•เฉฐเจŸเฉ‡เจจเจฐ เจจเฉ‚เฉฐ เจชเฉเจฐเจฎเจพเจฃเจฟเจค เจ…เจคเฉ‡ เจฒเฉ‹เจก เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚เฅค

    docker login -u USER -p PASSWORD registry.gitlab.com
    docker push registry.gitlab.com/group/deploy

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

เจ—เจฟเฉฑเจŸเจฒเจพเจฌ เจธเฉ€.เจ†เจˆ.

เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฒเจพเจ—เฉ‚ เจ•เจฐเฉ‹

เจกเจฟเจชเจฒเฉ‹เจ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฆเฉ‡ เจฐเฉ‚เจŸ เจตเจฟเฉฑเจš .gitlab-ci.yml เจซเจพเจˆเจฒ เจธเจผเจพเจฎเจฒ เจ•เจฐเฉ‹
เจธเจ•เฉเจฐเจฟเจชเจŸ เจฆเฉ‹ เจ†เจชเจธเฉ€ เจตเจฟเจธเจผเฉ‡เจธเจผ เจคเฉˆเจจเจพเจคเฉ€ เจ•เจพเจฐเจœเจพเจ‚ เจจเฉ‚เฉฐ เจชเฉ‡เจธเจผ เจ•เจฐเจฆเฉ€ เจนเฉˆเฅค เจ•เฉเจฐเจฎเจตเจพเจฐ เจ–เจพเจธ เจฆเฉŒเฉœเจพเจ• เจœเจพเจ‚ เจธเจพเจ‚เจเจพ เจฆเฉŒเฉœเจพเจ•เฅค

.gitlab-ci.yml

stages:
  - deploy

Specific Runner:
  extends: .java_deploy_template
  # ะ—ะฐะดะฐั‡ะฐ ะฑัƒะดะตั‚ ะฒั‹ะฟะพะปะฝัั‚ัŒัั ะฝะฐ ะฒะฐัˆะตะผ shell-ั€ะฐะฝะฝะตั€ะต
  tags:
    - deploy

Shared Runner:
  extends: .java_deploy_template
  # ะ—ะฐะดะฐั‡ะฐ ะฑัƒะดะตั‚ ะฒั‹ะฟะพะปะฝัั‚ัŒัั ะฝะฐ ะฟัƒะฑะปะธั‡ะฝะพะผ docker-ั€ะฐะฝะฝะตั€ะต
  tags:
    - docker
  # ะžะฑั€ะฐะท ะธะท ั€ะฐะทะดะตะปะฐ GitLab Runner -> Shared Runner -> Docker
  image: registry.gitlab.com/group/deploy-project:latest
  before_script:
    # ะ˜ะผะฟะพั€ั‚ะธั€ัƒะตะผ GPG ะบะปัŽั‡
    - printf "${GPG_SECRET_KEY}" | gpg --batch --import
    # ะกะพั…ั€ะฐะฝัะตะผ maven ะบะพะฝั„ะธะณัƒั€ะฐั†ะธัŽ
    - printf "${SETTINGS_SECURITY_XML}" > ~/.m2/settings-security.xml
    - printf "${SETTINGS_XML}" > ~/.m2/settings.xml

.java_deploy_template:
  stage: deploy
  # ะ—ะฐะดะฐั‡ะฐ ัั€ะฐะฑะพั‚ะฐะตั‚ ะฟะพ ั‚ั€ะธะณะณะตั€ัƒ, ะตัะปะธ ะฟะตั€ะตะดะฐะฝะฐ ะฟะตั€ะตะผะตะฝะฝะฐั DEPLOY ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ java
  only:
    variables:
    - $DEPLOY == "java"
  variables:
    # ะพั‚ะบะปัŽั‡ะฐะตะผ ะบะปะพะฝะธั€ะพะฒะฐะฝะธะต ั‚ะตะบัƒั‰ะตะณะพ ะฟั€ะพะตะบั‚ะฐ
    GIT_STRATEGY: none
  script:
    # ะŸั€ะตะดะพัั‚ะฐะฒะปัะตะผ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ั…ั€ะฐะฝะตะฝะธั ะฟะฐั€ะพะปั ะฒ ะฝะตะทะฐัˆะธั„ั€ะพะฒะฐะฝะฝะพะผ ะฒะธะดะต
    - git config --global credential.helper store
    # ะกะพั…ั€ะฐะฝัะตะผ ะฒั€ะตะผะตะฝะฝั‹ะต ะบั€ะตะดั‹ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั gitlab-ci-token
    # ะขะพะบะตะฝ ั€ะฐะฑะพั‚ะฐะตั‚ ะดะปั ะฒัะตั… ะฟัƒะฑะปะธั‡ะฝั‹ั… ะฟั€ะพะตะบั‚ะพะฒ gitlab.com ะธ ะดะปั ะฟั€ะพะตะบั‚ะพะฒ ะณั€ัƒะฟะฟั‹
    - echo "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com" >> ~/.git-credentials
    # ะŸะพะปะฝะพัั‚ัŒัŽ ั‡ะธัั‚ะธะผ ั‚ะตะบัƒั‰ัƒัŽ ะดะธั€ะตะบั‚ะพั€ะธัŽ
    - rm -rf .* *
    # ะšะปะพะฝะธั€ัƒะตะผ ะฟั€ะพะตะบั‚ ะบะพั‚ะพั€ั‹ะน, ะฑัƒะดะตะผ ะดะตะฟะปะพะธั‚ัŒ ะฒ Sonatype Nexus
    - git clone ${DEPLOY_CI_REPOSITORY_URL} .
    # ะŸะตั€ะตะบะปัŽั‡ะฐะตะผัั ะฝะฐ ะฝัƒะถะฝั‹ะน ะบะพะผะผะธั‚
    - git checkout ${DEPLOY_CI_COMMIT_SHA} -f
    # ะ•ัะปะธ ั…ะพั‚ัŒ ะพะดะธะฝ pom.xml ัะพะดะตั€ะถะธั‚ ะฟะฐั€ะฐะผะตั‚ั€ autoReleaseAfterClose ะฒะฐะปะธะผ ัะฑะพั€ะบัƒ.
    # ะ’ ะฟั€ะพั‚ะธะฒะฝะพะผ ัะปัƒั‡ะฐะต ะตัั‚ัŒ ั€ะธัะบ ะทะฐะปะธั‚ัŒ ัั‹ั€ั‹ะต ะฐั€ั‚ะตั„ะฐะบั‚ั‹ ะฒ maven central
    - >
      for pom in $(find . -name pom.xml); do
        if [[ $(grep -q autoReleaseAfterClose "$pom" && echo $?) == 0 ]]; then
          echo "File $pom contains prohibited setting: <autoReleaseAfterClose>";
          exit 1;
        fi;
      done
    # ะ•ัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ DEPLOY_CI_COMMIT_TAG ะฟัƒัั‚ะพะน, ั‚ะพ ะฟั€ะธะฝัƒะดะธั‚ะตะปัŒะฝะพ ัั‚ะฐะฒะธะผ SNAPSHOT-ะฒะตั€ัะธัŽ
    - >
      if [[ "${DEPLOY_CI_COMMIT_TAG}" != "" ]]; then
        mvn versions:set -DnewVersion=${DEPLOY_CI_COMMIT_TAG}
      else
        VERSION=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)
        if [[ "${VERSION}" == *-SNAPSHOT ]]; then
          mvn versions:set -DnewVersion=${VERSION}
        else
          mvn versions:set -DnewVersion=${VERSION}-SNAPSHOT
        fi
      fi
    # ะ—ะฐะฟัƒัะบะฐะตะผ ะทะฐะดะฐั‡ัƒ ะฝะฐ ัะฑะพั€ะบัƒ ะธ ะดะตะฟะปะพะน ะฐั€ั‚ะตั„ะฐะบั‚ะพะฒ
    - mvn clean deploy -DskipTests=true

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ

เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸเจพเจ‚ เจตเจฟเฉฑเจš เจœเฉ‹ เจœเจจเจคเจ• เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€เจ†เจ‚ เจตเจฟเฉฑเจš เจ…เฉฑเจชเจฒเฉ‹เจก เจ•เฉ€เจคเฉ‡ เจœเจพเจฃเฉ‡ เจนเจจ, เจคเฉเจนเจพเจจเฉ‚เฉฐ เจฐเฉ€เจฒเฉ€เจœเจผ เจ…เจคเฉ‡ เจธเจจเฉˆเจชเจธเจผเจพเจŸ เจธเฉฐเจธเจ•เจฐเจฃเจพเจ‚ เจจเฉ‚เฉฐ เจกเจพเจŠเจจเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ 2 เจ•เจฆเจฎ เจœเฉ‹เฉœเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆเฅค

.gitlab-ci.yml

stages:
  - build
  - test
  - verify
  - deploy

<...>

Release:
  extends: .trigger_deploy
  # ะ—ะฐะฟัƒัะบะฐั‚ัŒ ะทะฐะดะฐั‡ัƒ ั‚ะพะปัŒะบะพ ะฟo ั‚ะตะณัƒ.
  only:
    - tags

Snapshot:
  extends: .trigger_deploy
  # ะ—ะฐะฟัƒัะบะฐะตะผ ะทะฐะดะฐั‡ัƒ ะฝะฐ ะฟัƒะฑะปะธะบะฐั†ะธัŽ SNAPSHOT ะฒะตั€ัะธะธ ะฒั€ัƒั‡ะฝัƒัŽ
  when: manual
  # ะะต ะทะฐะฟัƒัะบะฐั‚ัŒ ะทะฐะดะฐั‡ัƒ, ะตัะปะธ ะฟั€ะพัั‚ะฐะฒะปะตะฝ ั‚ะตะณ.
  except:
    - tags

.trigger_deploy:
  stage: deploy
  variables:
    # ะžั‚ะบะปัŽั‡ะฐะตะผ ะบะปะพะฝะธั€ะพะฒะฐะฝะธะต ั‚ะตะบัƒั‰ะตะณะพ ะฟั€ะพะตะบั‚ะฐ
    GIT_STRATEGY: none
    # ะกัั‹ะปะบะฐ ะฝะฐ ั‚ั€ะธะณะณะตั€ deploy-ะทะฐะดะฐั‡ะธ
    URL: "https://gitlab.com/api/v4/projects/<deploy project ID>/trigger/pipeline"
    # ะŸะตั€ะตะผะตะฝะฝั‹ะต deploy-ะทะฐะดะฐั‡ะธ
    POST_DATA: "
      token=${DEPLOY_TOKEN}&
      ref=master&
      variables[DEPLOY]=${DEPLOY}&
      variables[DEPLOY_CI_REPOSITORY_URL]=${CI_REPOSITORY_URL}&
      variables[DEPLOY_CI_PROJECT_NAME]=${CI_PROJECT_NAME}&
      variables[DEPLOY_CI_COMMIT_SHA]=${CI_COMMIT_SHA}&
      variables[DEPLOY_CI_COMMIT_TAG]=${CI_COMMIT_TAG}
      "
  script:
    # ะะต ะธัะฟะพะปัŒะทัƒัŽ cURL, ั‚ะฐะบ ะบะฐะบ ั ั„ะปะฐะณะฐะผะธ --fail --show-error
    # ะพะฝ ะฝะต ะฒั‹ะฒะพะดะธั‚ ั‚ะตะปะพ ะพั‚ะฒะตั‚ะฐ, ะตัะปะธ HTTP ะบะพะด 400 ะธ ะฑะพะปะตะต 
    - wget --content-on-error -qO- ${URL} --post-data ${POST_DATA}

เจ‡เจธ เจนเฉฑเจฒ เจตเจฟเฉฑเจš, เจฎเฉˆเจ‚ เจฅเฉ‹เฉœเจพ เจนเฉ‹เจฐ เจ…เฉฑเจ—เฉ‡ เจ—เจฟเจ† เจ…เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸเจพเจ‚ เจฒเจˆ เจ‡เฉฑเจ• เจธเฉ€เจ†เจˆ เจŸเฉˆเจ‚เจชเจฒเฉ‡เจŸ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจจ เจฆเจพ เจซเฉˆเจธเจฒเจพ เจ•เฉ€เจคเจพ.

เจนเฉ‹เจฐ เจตเฉ‡เจฐเจตเฉ‡

เจฎเฉˆเจ‚ เจ‡เฉฑเจ• เจตเฉฑเจ–เจฐเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฌเจฃเจพเจ‡เจ† เจนเฉˆ gitlab-ci เจœเจฟเจธ เจตเจฟเฉฑเจš เจฎเฉˆเจ‚ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸเจพเจ‚ เจฒเจˆ เจ‡เฉฑเจ• CI เจŸเฉˆเจ‚เจชเจฒเฉ‡เจŸ เจฐเฉฑเจ–เจฟเจ† เจนเฉˆ common.yml.

common.yml

stages:
  - build
  - test
  - verify
  - deploy

variables:
  SONAR_ARGS: "
  -Dsonar.gitlab.commit_sha=${CI_COMMIT_SHA} 
  -Dsonar.gitlab.ref_name=${CI_COMMIT_REF_NAME} 
  "

.build_java_project:
  stage: build
  tags:
    - touchbit-shell
  variables:
    SKIP_TEST: "false"
  script:
    - mvn clean
    - mvn package -DskipTests=${SKIP_TEST}
  artifacts:
    when: always
    expire_in: 30 day
    paths:
      - "*/target/reports"

.build_sphinx_doc:
  stage: build
  tags:
    - touchbit-shell
  variables:
    DOCKERFILE: .indirect/docs/Dockerfile
  script:
    - docker build --no-cache -t ${CI_PROJECT_NAME}/doc -f ${DOCKERFILE} .

.junit_module_test_run:
  stage: test
  tags:
    - touchbit-shell
  variables:
    MODULE: ""
  script:
    - cd ${MODULE}
    - mvn test
  artifacts:
    when: always
    expire_in: 30 day
    paths:
      - "*/target/reports"

.junit_test_run:
  stage: test
  tags:
    - touchbit-shell
  script:
    - mvn test
  artifacts:
    when: always
    expire_in: 30 day
    paths:
    - "*/target/reports"

.sonar_review:
  stage: verify
  tags:
    - touchbit-shell
  dependencies: []
  script:
    - >
      if [ "$CI_BUILD_REF_NAME" == "master" ]; then
        mvn compile sonar:sonar -Dsonar.login=$SONAR_LOGIN $SONAR_ARGS
      else
        mvn compile sonar:sonar -Dsonar.login=$SONAR_LOGIN $SONAR_ARGS -Dsonar.analysis.mode=preview
      fi

.trigger_deploy:
  stage: deploy
  tags:
    - touchbit-shell
  variables:
    URL: "https://gitlab.com/api/v4/projects/10345765/trigger/pipeline"
    POST_DATA: "
      token=${DEPLOY_TOKEN}&
      ref=master&
      variables[DEPLOY]=${DEPLOY}&
      variables[DEPLOY_CI_REPOSITORY_URL]=${CI_REPOSITORY_URL}&
      variables[DEPLOY_CI_PROJECT_NAME]=${CI_PROJECT_NAME}&
      variables[DEPLOY_CI_COMMIT_SHA]=${CI_COMMIT_SHA}&
      variables[DEPLOY_CI_COMMIT_TAG]=${CI_COMMIT_TAG}
      "
  script:
  - wget --content-on-error -qO- ${URL} --post-data ${POST_DATA}

.trigger_release_deploy:
  extends: .trigger_deploy
  only:
    - tags

.trigger_snapshot_deploy:
  extends: .trigger_deploy
  when: manual
  except:
    - tags

เจจเจคเฉ€เจœเฉ‡ เจตเจœเฉ‹เจ‚, เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸเจพเจ‚ เจตเจฟเฉฑเจš, .gitlab-ci.yml เจฌเจนเฉเจค เจธเฉฐเจ–เฉ‡เจช เจฆเจฟเจ–เจพเจˆ เจฆเจฟเฉฐเจฆเจพ เจนเฉˆ เจ…เจคเฉ‡ เจตเจฐเจฌเฉ‹เจœเจผ เจจเจนเฉ€เจ‚

.gitlab-ci.yml

include: https://gitlab.com/TouchBIT/gitlab-ci/raw/master/common.yml

Shields4J:
  extends: .build_java_project

Sphinx doc:
  extends: .build_sphinx_doc
  variables:
    DOCKERFILE: .docs/Dockerfile

Sonar review:
  extends: .sonar_review
  dependencies:
    - Shields4J

Release:
  extends: .trigger_release_deploy

Snapshot:
  extends: .trigger_snapshot_deploy

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

Pom.xml เจธเฉฐเจฐเจšเจจเจพ

เจ‡เจธ เจตเจฟเจธเจผเฉ‡ เจจเฉ‚เฉฐ เจฌเจนเฉเจค เจตเจฟเจธเจฅเจพเจฐ เจจเจพเจฒ เจฆเฉฑเจธเจฟเจ† เจ—เจฟเจ† เจนเฉˆ. Googolplex ะฒ เจธเจจเฉˆเจชเจธเจผเจพเจŸ เจ…เจคเฉ‡ เจธเจŸเฉ‡เจœเจฟเฉฐเจ— เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€เจ†เจ‚ เจฒเจˆ เจ•เจฒเจพเจคเจฎเจ• เจšเฉ€เจœเจผเจพเจ‚ เจจเฉ‚เฉฐ เจธเจตเฉˆเจšเจฒเจฟเจค เจคเฉŒเจฐ 'เจคเฉ‡ เจธเจพเจˆเจจ เจ•เจฐเจจ เจ…เจคเฉ‡ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ เจฎเจพเจตเฉ‡เจจ เจจเฉ‚เฉฐ เจธเฉˆเฉฑเจŸ เจ•เจฐเจจเจพ, เจ‡เจธ เจฒเจˆ เจฎเฉˆเจ‚ เจชเจฒเฉฑเจ—เจ‡เจจ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจจ เจฆเฉ€เจ†เจ‚ เจ•เฉเจ เจธเฉ‚เจ–เจฎเจคเจพเจตเจพเจ‚ เจฆเจพ เจตเจฐเจฃเจจ เจ•เจฐเจพเจ‚เจ—เจพเฅค เจฎเฉˆเจ‚ เจ‡เจน เจตเฉ€ เจตเจฐเจฃเจจ เจ•เจฐเจพเจ‚เจ—เจพ เจ•เจฟ เจคเฉเจธเฉ€เจ‚ เจ•เจฟเฉฐเจจเฉ€ เจ†เจธเจพเจจ เจ…เจคเฉ‡ เจ†เจฐเจพเจฎเจฆเจพเจ‡เจ• เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹ nexus-staging-maven-pluginเจœเฉ‡เจ•เจฐ เจคเฉเจธเฉ€เจ‚ org.sonatype.oss:oss-parent เจจเฉ‚เฉฐ เจ†เจชเจฃเฉ‡ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฒเจˆ เจฎเจพเจ‚-เจชเจฟเจ“ เจตเจœเฉ‹เจ‚ เจจเจนเฉ€เจ‚ เจตเจฐเจคเจฃเจพ เจšเจพเจนเฉเฉฐเจฆเฉ‡ เจœเจพเจ‚ เจจเจนเฉ€เจ‚ เจตเจฐเจค เจธเจ•เจฆเฉ‡เฅค

maven-install-plugin

เจธเจฅเจพเจจเจ• เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจตเจฟเฉฑเจš เจฎเฉ‹เจกเฉ€เจŠเจฒ เจธเจฅเจพเจชเจค เจ•เจฐเจฆเจพ เจนเฉˆเฅค
เจฆเฉ‚เจœเฉ‡ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸเจพเจ‚ เจตเจฟเฉฑเจš เจนเฉฑเจฒเจพเจ‚ เจฆเฉ€ เจธเจฅเจพเจจเจ• เจคเจธเจฆเฉ€เจ• เจฒเจˆ เจฌเจนเฉเจค เจ‰เจชเจฏเฉ‹เจ—เฉ€ เจนเฉˆ, เจจเจพเจฒ เจนเฉ€ เจ‡เฉฑเจ• เจšเฉˆเจ•เจธเจฎ.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-install-plugin</artifactId>
  <executions>
    <execution>
      <id>install-project</id>
      <!-- ะ•ัะปะธ ัƒ ะฒะฐั ะผะฝะพะณะพะผะพะดัƒะปัŒะฝั‹ะน ะฟั€ะพะตะบั‚ ั ะดะตะฟะปะพะตะผ ั€ะพะดะธั‚ะตะปัŒัะบะพะณะพ ะฟะพะผะธะบะฐ -->
      <phase>install</phase>
      <!-- ะฏะฒะฝะพ ัƒะบะฐะทั‹ะฒะฐะตะผ ั„ะฐะนะปั‹ ะดะปั ะปะพะบะฐะปัŒะฝะพะน ัƒัั‚ะฐะฝะพะฒะบะธ -->
      <configuration>
        <file>target/${project.artifactId}-${project.version}.jar</file>
```target/${project.artifactId}-${project.version}-sources.jar</sources>
        <pomFile>dependency-reduced-pom.xml</pomFile>
        <!-- ะŸั€ะธะฝัƒะดะธั‚ะตะปัŒะฝะพะต ะพะฑะฝะพะฒะปะตะฝะธะต ะผะตั‚ะฐะดะฐะฝะฝั‹ั… ะฟั€ะพะตะบั‚ะฐ -->
        <updateReleaseInfo>true</updateReleaseInfo>
        <!-- ะšะพะฝั‚ั€ะพะปัŒะฝั‹ะต ััƒะผะผั‹ ะดะปั ะฟั€ะพะฒะตั€ะบะธ ั†ะตะปะพัั‚ะฝะพัั‚ะธ -->
        <createChecksum>true</createChecksum>
      </configuration>
    </execution>
  </executions>
</plugin>

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

maven-javadoc-เจชเจฒเฉฑเจ—เจ‡เจจ

เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฒเจˆ javadoc เจคเจฟเจ†เจฐ เจ•เฉ€เจคเจพ เจœเจพ เจฐเจฟเจนเจพ เจนเฉˆเฅค

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-javadoc-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>jar</goal>
      </goals>
      <!-- ะ“ะตะฝะตั€ะฐั†ะธั javadoc ะดะพะปะถะฝะฐ ะฑั‹ั‚ัŒ ะฟะพัะปะต ั„ะฐะทั‹ ะณะตะฝะตั€ะฐั†ะธะธ ั€ะตััƒั€ัะพะฒ -->
      <phase>prepare-package</phase>
      <configuration>
        <!-- ะžั‡ะตะฝัŒ ะฟะพะผะพะณะฐะตั‚ ะฒ ะฟัƒะฑะปะธั‡ะฝั‹ั… ะฟั€ะพะตะบั‚ะฐั… -->
        <failOnError>true</failOnError>
        <failOnWarnings>true</failOnWarnings>
        <!-- ะฃะฑะธั€ะฐะตั‚ ะพัˆะธะฑะบัƒ ะฟะพะธัะบะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะฒ target ะดะธั€ะตะบั‚ะพั€ะธะธ -->
        <detectOfflineLinks>false</detectOfflineLinks>
      </configuration>
    </execution>
  </executions>
</plugin>

เจœเฉ‡เจ•เจฐ เจคเฉเจนเจพเจกเฉ‡ เจ•เฉ‹เจฒ เจ‡เฉฑเจ• เจฎเฉ‹เจกเฉ€เจŠเจฒ เจนเฉˆ เจœเจฟเจธ เจตเจฟเฉฑเจš เจœเจพเจตเจพ เจธเจผเจพเจฎเจฒ เจจเจนเฉ€เจ‚ เจนเฉˆ (เจ‰เจฆเจพเจนเจฐเจฃ เจฒเจˆ เจธเจฟเจฐเจซเจผ เจธเจฐเฉ‹เจค)
เจœเจพเจ‚ เจคเฉเจธเฉ€เจ‚ เจธเจฟเจงเจพเจ‚เจค เจตเจฟเฉฑเจš javadoc เจฌเจฃเจพเจ‰เจฃเจพ เจจเจนเฉ€เจ‚ เจšเจพเจนเฉเฉฐเจฆเฉ‡ เจนเฉ‹, เจซเจฟเจฐ เจฎเจฆเจฆ เจ•เจฐเฉ‹ maven-jar-plugin

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <executions>
    <execution>
      <id>empty-javadoc-jar</id>
      <phase>generate-resources</phase>
      <goals>
        <goal>jar</goal>
      </goals>
      <configuration>
        <classifier>javadoc</classifier>
        <classesDirectory>${basedir}/javadoc</classesDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

maven-gpg-เจชเจฒเฉฑเจ—เจ‡เจจ

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-gpg-plugin</artifactId>
  <executions>
    <execution>
      <id>sign-artifacts</id>
      <!-- ะกะฑะพั€ะบะฐ ะฑัƒะดะตั‚ ะฟะฐะดะฐั‚ัŒ, ะตัะปะธ ะพั‚ััƒั‚ัั‚ะฒัƒะตั‚ GPG ะบะปัŽั‡ -->
      <!-- ะŸะพะดะฟะธัั‹ะฒะฐะตะผ ะฐั€ั‚ะตั„ะฐะบั‚ั‹ ั‚ะพะปัŒะบะพ ะฝะฐ ั„ะฐะทะต deploy -->
      <phase>deploy</phase>
      <goals>
        <goal>sign</goal>
      </goals>
    </execution>
  </executions>
</plugin>

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

nexus-staging-maven-plugin

เจธเฉฐเจฐเจšเจจเจพ:

<project>
  <!-- ... -->
  <build>
    <plugins>
      <!-- ... -->
      <plugin>
        <groupId>org.sonatype.plugins</groupId>
        <artifactId>nexus-staging-maven-plugin</artifactId>
      </plugin>
    </plugins>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.sonatype.plugins</groupId>
          <artifactId>nexus-staging-maven-plugin</artifactId>
          <extensions>true</extensions>
          <configuration>
            <serverId>sonatype</serverId>
            <nexusUrl>https://oss.sonatype.org/</nexusUrl>
            <!-- ะžะฑะฝะพะฒะปัะตะผ ะผะตั‚ะฐะดะฐะฝะฝั‹ะต, ั‡ั‚ะพะฑั‹ ะฟะพะผะตั‚ะธั‚ัŒ ะฐั€ั‚ะตั„ะฐะบั‚ ะบะฐะบ release -->
            <!-- ะะต ะฒะปะธัะตั‚ ะฝะฐ snapshot ะฒะตั€ัะธะธ -->
            <updateReleaseInfo>true</updateReleaseInfo>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-deploy-plugin</artifactId>
          <configuration>
            <!-- ะžั‚ะบะปัŽั‡ะฐะตะผ ะฟะปะฐะณะธะฝ -->
            <skip>true</skip>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
  <distributionManagement>
    <snapshotRepository>
      <id>sonatype</id>
      <name>Nexus Snapshot Repository</name>
      <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
    </snapshotRepository>
    <repository>
      <id>sonatype</id>
      <name>Nexus Release Repository</name>
      <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
    </repository>
  </distributionManagement>
</project>

เจœเฉ‡เจ•เจฐ เจคเฉเจนเจพเจกเฉ‡ เจ•เฉ‹เจฒ เจ‡เฉฑเจ• เจฎเจฒเจŸเฉ€-เจฎเฉ‹เจกเจฟเจŠเจฒ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจนเฉˆ เจ…เจคเฉ‡ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจตเจฟเฉฑเจš เจ‡เฉฑเจ• เจ–เจพเจธ เจฎเฉ‹เจกเฉ€เจŠเจฒ เจ…เฉฑเจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจจเจนเฉ€เจ‚ เจนเฉˆ, เจคเจพเจ‚ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจœเฉ‹เฉœเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ nexus-staging-maven-plugin เจเฉฐเจกเฉ‡ เจฆเฉ‡ เจจเจพเจฒ skipNexusStagingDeployMojo

<build>
  <plugins>
    <plugin>
      <groupId>org.sonatype.plugins</groupId>
      <artifactId>nexus-staging-maven-plugin</artifactId>
      <configuration>
        <skipNexusStagingDeployMojo>true</skipNexusStagingDeployMojo>
      </configuration>
    </plugin>
  </plugins>
</build>

เจกเจพเจ‰เจจเจฒเฉ‹เจก เจ•เจฐเจจ เจคเฉ‹เจ‚ เจฌเจพเจ…เจฆ, เจธเจจเฉˆเจชเจธเจผเจพเจŸ/เจฐเจฟเจฒเฉ€เจœเจผ เจตเจฐเจœเจจ เจตเจฟเฉฑเจš เจ‰เจชเจฒเจฌเจง เจนเจจ เจธเจŸเฉ‡เจœเจฟเฉฐเจ— เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€เจ†เจ‚

<repositories>
  <repository>
    <id>SonatypeNexus</id>
    <url>https://oss.sonatype.org/content/groups/staging/</url>
    <!-- ะะต ะฝะฐะดะพ ัƒะบะฐะทั‹ะฒะฐั‚ัŒ ั„ะปะฐะณะธ snapshot/release ะดะปั ั€ะตะฟะพะทะธั‚ะพั€ะธั -->
  </repository>
</repositories>

เจนเฉ‹เจฐ เจชเจฒเฉฑเจธ

  • เจจเฉ‡เจ•เจธเจธ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ (mvn help:describe -Dplugin=org.sonatype.plugins:nexus-staging-maven-plugin).
  • เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ เจ†เจŸเฉ‹เจฎเฉˆเจŸเจฟเจ• เจฐเฉ€เจฒเฉ€เจœเจผ เจœเจพเจ‚เจš

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

เจ‡เจธ เจฆเจพ เจจเจคเฉ€เจœเจพ

SNAPSHOT เจธเฉฐเจธเจ•เจฐเจฃ เจชเฉเจฐเจ•เจพเจธเจผเจฟเจค เจ•เฉ€เจคเจพ เจœเจพ เจฐเจฟเจนเจพ เจนเฉˆ

เจ‡เฉฑเจ• เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฌเจฃเจพเจ‰เจ‚เจฆเฉ‡ เจธเจฎเฉ‡เจ‚, เจ—เจ เจœเฉ‹เฉœ เจตเจฟเฉฑเจš เจธเจจเฉˆเจชเจธเจผเฉŒเจŸ เจธเฉฐเจธเจ•เจฐเจฃ เจจเฉ‚เฉฐ เจกเจพเจ‰เจจเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ เจ‡เฉฑเจ• เจ•เจพเจฐเจœ เจจเฉ‚เฉฐ เจฆเจธเจคเฉ€ เจฒเจพเจ‚เจš เจ•เจฐเจจเจพ เจธเฉฐเจญเจต เจนเฉˆ

เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

เจœเจฆเฉ‹เจ‚ เจ‡เจน เจŸเจพเจธเจ• เจฒเจพเจ‚เจš เจ•เฉ€เจคเจพ เจœเจพเจ‚เจฆเจพ เจนเฉˆ, เจคเฉˆเจจเจพเจค เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจตเจฟเฉฑเจš เจธเฉฐเจฌเฉฐเจงเจฟเจค เจ•เฉฐเจฎ เจธเจผเฉเจฐเฉ‚ เจนเฉ‹ เจœเจพเจ‚เจฆเจพ เจนเฉˆ (เจ‰เจฆเจพเจนเจฐเจจ).

เจ•เฉฑเจŸเจฟเจ† เจนเฉ‹เจ‡เจ† เจฒเฉŒเจ—

Running with gitlab-runner 11.10.0 (3001a600)
  on Deploy runner JSKWyxUw
Using Shell executor...
Running on ih1174328.vds.myihor.ru...
Skipping Git repository setup
Skipping Git checkout
Skipping Git submodules setup
$ rm -rf .* *
$ git config --global credential.helper store
$ echo "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com" >> ~/.git-credentials
$ git clone ${DEPLOY_CI_REPOSITORY_URL} .
Cloning into 'shields4j'...
$ git checkout ${DEPLOY_CI_COMMIT_SHA}
Note: checking out '850f86aa317194395c5387790da1350e437125a7'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
  git checkout -b new_branch_name
HEAD is now at 850f86a... skip deploy test-core
$ for pom in $(find . -name pom.xml); do # collapsed multi-line command
$ if [[ "${DEPLOY_CI_COMMIT_TAG}" != "" ]]; then # collapsed multi-line command
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 4 modules...
[INFO] Installing Nexus Staging features:
[INFO]   ... total of 4 executions of maven-deploy-plugin replaced with nexus-staging-maven-plugin
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] Shields4J                                                          [pom]
[INFO] test-core                                                          [jar]
[INFO] Shields4J client                                                   [jar]
[INFO] TestNG listener                                                    [jar]
[INFO] 
[INFO] --------------< org.touchbit.shields4j:shields4j-parent >---------------
[INFO] Building Shields4J 1.0.0                                           [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] 
[INFO] --- versions-maven-plugin:2.5:set (default-cli) @ shields4j-parent ---
[INFO] Searching for local aggregator root...
[INFO] Local aggregation root: /home/gitlab-deployer/JSKWyxUw/0/TouchBIT/deploy/shields4j
[INFO] Processing change of org.touchbit.shields4j:shields4j-parent:1.0.0 -> 1.0.0-SNAPSHOT
[INFO] Processing org.touchbit.shields4j:shields4j-parent
[INFO]     Updating project org.touchbit.shields4j:shields4j-parent
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO] 
[INFO] Processing org.touchbit.shields4j:client
[INFO]     Updating parent org.touchbit.shields4j:shields4j-parent
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO]     Updating dependency org.touchbit.shields4j:test-core
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO] 
[INFO] Processing org.touchbit.shields4j:test-core
[INFO]     Updating parent org.touchbit.shields4j:shields4j-parent
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO] 
[INFO] Processing org.touchbit.shields4j:testng
[INFO]     Updating parent org.touchbit.shields4j:shields4j-parent
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO]     Updating dependency org.touchbit.shields4j:client
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO]     Updating dependency org.touchbit.shields4j:test-core
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] Shields4J 1.0.0 .................................... SUCCESS [  0.992 s]
[INFO] test-core .......................................... SKIPPED
[INFO] Shields4J client ................................... SKIPPED
[INFO] TestNG listener 1.0.0 .............................. SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.483 s
[INFO] Finished at: 2019-04-21T02:40:42+03:00
[INFO] ------------------------------------------------------------------------
$ mvn clean deploy -DskipTests=${SKIP_TESTS}
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 4 modules...
[INFO] Installing Nexus Staging features:
[INFO]   ... total of 4 executions of maven-deploy-plugin replaced with nexus-staging-maven-plugin
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] Shields4J                                                          [pom]
[INFO] test-core                                                          [jar]
[INFO] Shields4J client                                                   [jar]
[INFO] TestNG listener                                                    [jar]
[INFO] 
[INFO] --------------< org.touchbit.shields4j:shields4j-parent >---------------
[INFO] Building Shields4J 1.0.0-SNAPSHOT                                  [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
...
DELETED
...
[INFO]  * Bulk deploy of locally gathered snapshot artifacts finished.
[INFO] Remote deploy finished with success.
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] Shields4J 1.0.0-SNAPSHOT ........................... SUCCESS [  2.375 s]
[INFO] test-core .......................................... SUCCESS [  3.929 s]
[INFO] Shields4J client ................................... SUCCESS [  3.815 s]
[INFO] TestNG listener 1.0.0-SNAPSHOT ..................... SUCCESS [ 36.134 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 47.629 s
[INFO] Finished at: 2019-04-21T02:41:32+03:00
[INFO] ------------------------------------------------------------------------

เจจเจคเฉ€เจœเฉ‡ เจตเจœเฉ‹เจ‚, เจธเฉฐเจธเจ•เจฐเจฃ เจ—เจ เจœเฉ‹เฉœ เจตเจฟเฉฑเจš เจฒเฉ‹เจก เจนเฉ‹ เจ—เจฟเจ† เจนเฉˆ 1.0.0-เจธเจจเฉˆเจชเจธเจผเจพเจŸ.

เจธเจพเจฐเฉ‡ เจธเจจเฉˆเจชเจธเจผเจพเจŸ เจธเฉฐเจธเจ•เจฐเจฃเจพเจ‚ เจจเฉ‚เฉฐ เจตเฉˆเจฌเจธเจพเจˆเจŸ 'เจคเฉ‡ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจคเฉ‹เจ‚ เจฎเจฟเจŸเจพเจ‡เจ† เจœเจพ เจธเจ•เจฆเจพ เจนเฉˆ oss.sonatype.org เจคเฉเจนเจพเจกเฉ‡ เจ–เจพเจคเฉ‡ เจฆเฉ‡ เจ…เจงเฉ€เจจ.

เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

เจ‡เฉฑเจ• เจฐเฉ€เจฒเฉ€เจœเจผ เจธเฉฐเจธเจ•เจฐเจฃ เจชเฉเจฐเจ•เจพเจธเจผเจฟเจค เจ•เฉ€เจคเจพ เจœเจพ เจฐเจฟเจนเจพ เจนเฉˆ

เจœเจฆเฉ‹เจ‚ เจ‡เฉฑเจ• เจŸเฉˆเจ— เจธเจฅเจพเจชเจค เจ•เฉ€เจคเจพ เจœเจพเจ‚เจฆเจพ เจนเฉˆ, เจคเจพเจ‚ เจกเจฟเจชเจฒเฉ‹เจ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจตเจฟเฉฑเจš เจธเฉฐเจฌเฉฐเจงเจฟเจค เจ•เฉฐเจฎ เจจเฉ‚เฉฐ เจฐเฉ€เจฒเฉ€เจœเจผ เจตเจฐเจœเจจ เจจเฉ‚เฉฐ เจจเฉ‡เจ•เจธเจธ (เจ‰เจฆเจพเจนเจฐเจจ).

เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

เจธเจญ เจคเฉ‹เจ‚ เจตเจงเฉ€เจ† เจ—เฉฑเจฒ เจ‡เจน เจนเฉˆ เจ•เจฟ เจจเจœเจผเจฆเฉ€เจ•เฉ€ เจฐเฉ€เจฒเฉ€เจœเจผ เจ—เจ เจœเฉ‹เฉœ เจตเจฟเฉฑเจš เจ†เจชเจฃเฉ‡ เจ†เจช เจšเจพเจฒเฉ‚ เจนเฉ‹ เจœเจพเจ‚เจฆเฉ€ เจนเฉˆเฅค

[INFO] Performing remote staging...
[INFO] 
[INFO]  * Remote staging into staging profile ID "9043b43f77dcc9"
[INFO]  * Created staging repository with ID "orgtouchbit-1037".
[INFO]  * Staging repository at https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1037
[INFO]  * Uploading locally staged artifacts to profile org.touchbit
[INFO]  * Upload of locally staged artifacts finished.
[INFO]  * Closing staging repository with ID "orgtouchbit-1037".
Waiting for operation to complete...
.........
[INFO] Remote staged 1 repositories, finished with success.
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] Shields4J 1.0.0 .................................... SUCCESS [  9.603 s]
[INFO] test-core .......................................... SUCCESS [  3.419 s]
[INFO] Shields4J client ................................... SUCCESS [  9.793 s]
[INFO] TestNG listener 1.0.0 .............................. SUCCESS [01:23 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:47 min
[INFO] Finished at: 2019-04-21T04:05:46+03:00
[INFO] ------------------------------------------------------------------------

เจ…เจคเฉ‡ เจœเฉ‡ เจ•เฉเจ เจ—เจฒเจค เจนเฉ‹ เจœเจพเจ‚เจฆเจพ เจนเฉˆ, เจคเจพเจ‚ เจ•เฉฐเจฎ เจฏเจ•เฉ€เจจเฉ€ เจคเฉŒเจฐ 'เจคเฉ‡ เจ…เจธเจซเจฒ เจนเฉ‹ เจœเจพเจตเฉ‡เจ—เจพ

[INFO] Performing remote staging...
[INFO] 
[INFO]  * Remote staging into staging profile ID "9043b43f77dcc9"
[INFO]  * Created staging repository with ID "orgtouchbit-1038".
[INFO]  * Staging repository at https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1038
[INFO]  * Uploading locally staged artifacts to profile org.touchbit
[INFO]  * Upload of locally staged artifacts finished.
[INFO]  * Closing staging repository with ID "orgtouchbit-1038".
Waiting for operation to complete...
.......
[ERROR] Rule failure while trying to close staging repository with ID "orgtouchbit-1039".
[ERROR] 
[ERROR] Nexus Staging Rules Failure Report
[ERROR] ==================================
[ERROR] 
[ERROR] Repository "orgtouchbit-1039" failures
[ERROR]   Rule "signature-staging" failures
[ERROR]     * No public key: Key with id: (1f42b618d1cbe1b5) was not able to be located on &lt;a href=http://keys.gnupg.net:11371/&gt;http://keys.gnupg.net:11371/&lt;/a&gt;. Upload your public key and try the operation again.
...
[ERROR] Cleaning up local stage directory after a Rule failure during close of staging repositories: [orgtouchbit-1039]
[ERROR]  * Deleting context 9043b43f77dcc9.properties
[ERROR] Cleaning up remote stage repositories after a Rule failure during close of staging repositories: [orgtouchbit-1039]
[ERROR]  * Dropping failed staging repository with ID "orgtouchbit-1039" (Rule failure during close of staging repositories: [orgtouchbit-1039]).
[ERROR] Remote staging finished with a failure: Staging rules failure!
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] Shields4J 1.0.0 .................................... SUCCESS [  4.073 s]
[INFO] test-core .......................................... SUCCESS [  2.788 s]
[INFO] Shields4J client ................................... SUCCESS [  3.962 s]
[INFO] TestNG listener 1.0.0 .............................. FAILURE [01:07 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

เจจเจคเฉ€เจœเฉ‡ เจตเจœเฉ‹เจ‚, เจธเจพเจกเฉ‡ เจ•เฉ‹เจฒ เจธเจฟเจฐเจซเจผ เจ‡เฉฑเจ• เจตเจฟเจ•เจฒเจช เจฌเจšเจฟเจ† เจนเฉˆเฅค เจœเจพเจ‚ เจคเจพเจ‚ เจ‡เจธ เจธเฉฐเจธเจ•เจฐเจฃ เจจเฉ‚เฉฐ เจฎเจฟเจŸเจพเจ“ เจœเจพเจ‚ เจ‡เจธเจจเฉ‚เฉฐ เจชเฉเจฐเจ•เจพเจธเจผเจฟเจค เจ•เจฐเฉ‹เฅค

เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

เจฐเจฟเจฒเฉ€เจœเจผ เจนเฉ‹เจฃ เจคเฉ‹เจ‚ เจฌเจพเจ…เจฆ, เจ•เฉเจ เจธเจฎเฉ‡เจ‚ เจฌเจพเจ…เจฆ เจ•เจฒเจพเจ•เฉเจฐเจฟเจคเฉ€เจ†เจ‚ เจ…เฉฐเจฆเจฐ เจนเฉ‹ เจœเจพเจฃเจ—เฉ€เจ†เจ‚ เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ 'เจคเฉ‡ เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจจเฉ‚เฉฐ เจ…เจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ GitLab CI เจฆเฉ€ เจธเจฅเจพเจชเจจเจพ เจ•เจฐเจจเจพ

เจ”เจซเจŸเฉŒเจชเจฟเจ•

เจ‡เจน เจฎเฉ‡เจฐเฉ‡ เจฒเจˆ เจ‡เฉฑเจ• เจ–เฉ‹เจœ เจธเฉ€ เจœเฉ‹ เจฎเฉ‡เจตเฉ‡เจจ เจนเฉ‹เจฐ เจœเจจเจคเจ• เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€เจ†เจ‚ เจจเฉ‚เฉฐ เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจฌเจฃเจพเจ‰เจ‚เจฆเจพ เจนเฉˆ.
เจฎเฉˆเจจเฉ‚เฉฐ robots.txt เจจเฉ‚เฉฐ เจœเฉ‹เฉœเจจเจพ เจชเจฟเจ† เจ•เจฟเจ‰เจ‚เจ•เจฟ เจ‡เจน เจฎเฉ‡เจฐเฉ€ เจชเฉเจฐเจพเจฃเฉ€ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจจเฉ‚เฉฐ เจธเฉ‚เจšเฉ€เจฌเฉฑเจง เจ•เจฐเจฆเจพ เจนเฉˆเฅค

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

เจธเจฟเฉฑเจŸเจพ

เจธเจพเจกเฉ‡ เจ•เฉ‹เจฒ เจ•เฉ€ เจนเฉˆ

  • เจ‡เฉฑเจ• เจตเฉฑเจ–เจฐเจพ เจคเฉˆเจจเจพเจค เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจœเจฟเจธ เจตเจฟเฉฑเจš เจคเฉเจธเฉ€เจ‚ เจตเฉฑเจ–-เจตเฉฑเจ– เจตเจฟเจ•เจพเจธ เจญเจพเจธเจผเจพเจตเจพเจ‚ เจฒเจˆ เจœเจจเจคเจ• เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€เจ†เจ‚ เจตเจฟเฉฑเจš เจ•เจฒเจพเจ•เฉเจฐเจฟเจคเฉ€เจ†เจ‚ เจจเฉ‚เฉฐ เจ…เฉฑเจชเจฒเฉ‹เจก เจ•เจฐเจจ เจฒเจˆ เจ•เจˆ CI เจ•เจพเจฐเจœเจพเจ‚ เจจเฉ‚เฉฐ เจฒเจพเจ—เฉ‚ เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹เฅค
  • เจกเจฟเจชเจฒเฉ‹เจ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฌเจพเจนเจฐเฉ€ เจฆเจ–เจฒเจ…เฉฐเจฆเจพเจœเจผเฉ€ เจคเฉ‹เจ‚ เจตเฉฑเจ– เจ•เฉ€เจคเจพ เจ—เจฟเจ† เจนเฉˆ เจ…เจคเฉ‡ เจธเจฟเจฐเจซ เจฎเจพเจฒเจ• เจ…เจคเฉ‡ เจฐเฉฑเจ–-เจฐเจ–เจพเจ… เจ•เจฐเจจ เจตเจพเจฒเฉ‡ เจฐเฉ‹เจฒ เจตเจพเจฒเฉ‡ เจ‰เจชเจญเฉ‹เจ—เจคเจพเจตเจพเจ‚ เจฆเฉเจ†เจฐเจพ เจฌเจฆเจฒเจฟเจ† เจœเจพ เจธเจ•เจฆเจพ เจนเฉˆเฅค
  • เจธเจฟเจฐเจซเจผ เจคเฉˆเจจเจพเจค เจ•เจพเจฐเจœเจพเจ‚ เจจเฉ‚เฉฐ เจšเจฒเจพเจ‰เจฃ เจฒเจˆ "เจนเฉŒเจŸ" เจ•เฉˆเจธเจผ เจตเจพเจฒเจพ เจ‡เฉฑเจ• เจตเฉฑเจ–เจฐเจพ เจ–เจพเจธ เจฐเจจเจฐเฅค
  • เจœเจจเจคเจ• เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€ เจตเจฟเฉฑเจš เจธเจจเฉˆเจชเจธเจผเจพเจŸ/เจฐเจฟเจฒเฉ€เจœเจผ เจธเฉฐเจธเจ•เจฐเจฃเจพเจ‚ เจจเฉ‚เฉฐ เจชเฉเจฐเจ•เจพเจธเจผเจฟเจค เจ•เจฐเจจเจพเฅค
  • เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ เจตเจฟเฉฑเจš เจชเฉเจฐเจ•เจพเจธเจผเจจ เจฆเฉ€ เจคเจฟเจ†เจฐเฉ€ เจฒเจˆ เจฐเฉ€เจฒเฉ€เจœเจผ เจธเฉฐเจธเจ•เจฐเจฃ เจฆเฉ€ เจ†เจŸเฉ‹เจฎเฉˆเจŸเจฟเจ• เจœเจพเจ‚เจšเฅค
  • เจฎเจพเจตเฉ‡เจจ เจธเฉˆเจ‚เจŸเจฐเจฒ เจตเจฟเฉฑเจš "เจ•เฉฑเจšเฉ‡" เจธเฉฐเจธเจ•เจฐเจฃเจพเจ‚ เจฆเฉ‡ เจ†เจŸเฉ‹เจฎเฉˆเจŸเจฟเจ• เจชเฉเจฐเจ•เจพเจธเจผเจจ เจคเฉ‹เจ‚ เจธเฉเจฐเฉฑเจ–เจฟเจ†เฅค
  • "เจ•เจฒเจฟเฉฑเจ• 'เจคเฉ‡" เจธเจจเฉˆเจชเจธเจผเจพเจŸ เจธเฉฐเจธเจ•เจฐเจฃ เจฌเจฃเจพเจ“ เจ…เจคเฉ‡ เจชเฉเจฐเจ•เจพเจธเจผเจฟเจค เจ•เจฐเฉ‹เฅค
  • เจธเจจเฉˆเจชเจธเจผเจพเจŸ/เจฐเจฟเจฒเฉ€เจœเจผ เจตเจฐเจœเจจ เจชเฉเจฐเจพเจชเจค เจ•เจฐเจจ เจฒเจˆ เจ‡เฉฑเจ• เจธเจฟเฉฐเจ—เจฒ เจฐเจฟเจชเฉ‹เจœเจผเจŸเจฐเฉ€เฅค
  • เจœเจพเจตเจพ เจชเฉเจฐเฉ‹เจœเฉˆเจ•เจŸ เจฌเจฃเจพเจ‰เจฃ/เจŸเฉˆเจธเจŸเจฟเฉฐเจ—/เจชเฉเจฐเจ•เจพเจธเจผเจฟเจค เจ•เจฐเจจ เจฒเจˆ เจ†เจฎ เจชเจพเจˆเจชเจฒเจพเจˆเจจเฅค

GitLab CI เจจเฉ‚เฉฐ เจธเฉˆเจŸ เจ…เจช เจ•เจฐเจจเจพ เจ‡เฉฐเจจเจพ เจ—เฉเฉฐเจเจฒเจฆเจพเจฐ เจตเจฟเจธเจผเจพ เจจเจนเฉ€เจ‚ เจนเฉˆ เจœเจฟเฉฐเจจเจพ เจ‡เจน เจชเจนเจฟเจฒเฉ€ เจจเจœเจผเจฐ 'เจคเฉ‡ เจฒเฉฑเจ—เจฆเจพ เจนเฉˆ. เจŸเจฐเจจเจ•เฉ€ โ€‹โ€‹เจฆเฉ‡ เจ…เจงเจพเจฐ 'เจคเฉ‡ เจธเฉ€เจ†เจˆ เจจเฉ‚เฉฐ เจ•เจˆ เจตเจพเจฐ เจธเจฅเจพเจชเจค เจ•เจฐเจจเจพ เจ•เจพเจซเจผเฉ€ เจนเฉˆ, เจ…เจคเฉ‡ เจนเฉเจฃ เจคเฉเจธเฉ€เจ‚ เจ‡เจธ เจฎเจพเจฎเจฒเฉ‡ เจตเจฟเฉฑเจš เจธเจผเฉเจ•เฉ€เจจ เจคเฉ‹เจ‚ เจฌเจนเฉเจค เจฆเฉ‚เจฐ เจนเฉ‹เฅค เจ‡เจธ เจคเฉ‹เจ‚ เจ‡เจฒเจพเจตเจพ, GitLab เจฆเจธเจคเจพเจตเฉ‡เจœเจผ เจฌเจนเฉเจค เจฌเฉ‡เจฒเฉ‹เฉœเฉ‡ เจนเจจ. เจชเจนเจฟเจฒเจพ เจ•เจฆเจฎ เจšเฉเฉฑเจ•เจฃ เจคเฉ‹เจ‚ เจจเจพ เจกเจฐเฉ‹เฅค เจคเฉเจฐเจจ เจตเจพเจฒเฉ‡ เจตเจฟเจ…เจ•เจคเฉ€ เจฆเฉ‡ เจ•เจฆเจฎเจพเจ‚ เจฆเฉ‡ เจนเฉ‡เจ เจพเจ‚ เจธเฉœเจ• เจฆเจฟเจ–เจพเจˆ เจฆเจฟเฉฐเจฆเฉ€ เจนเฉˆ (เจฎเฉˆเจจเฉ‚เฉฐ เจฏเจพเจฆ เจจเจนเฉ€เจ‚ เจ•เจฟ เจ‡เจน เจ•เจฟเจธเจจเฉ‡ เจ•เจฟเจนเจพ :)

เจฎเฉˆเจจเฉ‚เฉฐ เจซเฉ€เจกเจฌเฉˆเจ• เจชเฉเจฐเจพเจชเจค เจ•เจฐเจ•เฉ‡ เจ–เฉเจธเจผเฉ€ เจนเฉ‹เจตเฉ‡เจ—เฉ€เฅค

เจ…เจ—เจฒเฉ‡ เจฒเฉ‡เจ– เจตเจฟเฉฑเจš เจฎเฉˆเจ‚ เจ‡เจธ เจฌเจพเจฐเฉ‡ เจ—เฉฑเจฒ เจ•เจฐเจพเจ‚เจ—เจพ เจ•เจฟ เจœเฉ‡ เจคเฉเจนเจพเจกเฉ‡ เจ•เฉ‹เจฒ เจธเจฟเจฐเจซ เจ‡เฉฑเจ• เจธเจผเฉˆเฉฑเจฒ เจฆเฉŒเฉœเจพเจ• เจนเฉˆ เจคเจพเจ‚ เจฎเฉˆเจ‚ เจ‡เจธ เจฌเจพเจฐเฉ‡ เจ—เฉฑเจฒ เจ•เจฐเจพเจ‚เจ—เจพ เจ•เจฟ เจเจ•เฉ€เจ•เจฐเจฃ เจŸเฉˆเจธเจŸเจพเจ‚ (เจกเฉŒเจ•เจฐ-เจ•เฉฐเจชเฉ‹เจœเจผ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจ•เฉ‡ เจŸเฉˆเจธเจŸ เจฆเฉ‡ เจ…เจงเฉ€เจจ เจธเฉ‡เจตเจพเจตเจพเจ‚ เจจเฉ‚เฉฐ เจšเจฒเจพเจ‰เจฃเจพ) เจฆเฉ‡ เจจเจพเจฒ เจ•เจพเจฐเจœเจพเจ‚ เจจเฉ‚เฉฐ เจšเจฒเจพเจ‰เจฃ เจฒเจˆ GitLab CI เจจเฉ‚เฉฐ เจ•เจฟเจตเฉ‡เจ‚ เจธเฉฐเจฐเจšเจฟเจค เจ•เจฐเจจเจพ เจนเฉˆเฅค

เจธเจฎเฉฑเจ—เจฐเฉ€ เจจเฉ‚เฉฐ

เจธเจฐเฉ‹เจค: www.habr.com

เจ‡เฉฑเจ• เจŸเจฟเฉฑเจชเจฃเฉ€ เจœเฉ‹เฉœเฉ‹