빌드에 실패한 커밋을 자동으로 되돌리기


43

저의 동료는 CI 서버가 빌드에 실패한 커밋을 되돌릴 것을 생각하고 있다고 말합니다. 그래서 HEADin master은 항상 안정적입니다 (적어도 빌드를 통과하는 것처럼).

이것이 최선의 방법 master입니까, 아니면 개발자가 고칠 때까지 깨지는 것보다 더 문제가 될 수 있습니까?

내 생각은 커밋을 되 돌리면 커밋 및 수정을 읽는 작업이 더 복잡해질 것입니다 (개발자는 되돌리기를 되 돌린 다음 수정을 커밋 git log해야합니다. 고치다. 내가 master안정 을 갖는 데에는 몇 가지 장점이 있지만 , 실패한 커밋을 되돌려 놓아도 설득력이 없다

편집 : 그것이 master아니면 다른 개발 지점인지 는 중요하지 않지만 질문은 동일하게 유지됩니다. CI 시스템이 빌드에 실패한 커밋을 되돌려 야합니까?

다른 (길이) 편집 : 좋아, 우리는 git이상한 방식으로 사용 하고 있습니다. 브랜치에 대한 커밋은 다른 개발자 및 변경 사항을 차단하고 브랜치를 다시 통합하고 가능한 충돌을 처리해야 할 때 시간을 추가하기 때문에 브랜치 개념은 실제 CI와 반대되는 것으로 생각합니다. 모든 사람 master이이 충돌에 대한 커밋을 최소화하면 모든 커밋이 모든 테스트를 통과합니다.

물론, 이것은 새로운 기능을 도입 할 때 이전 버전과의 호환성을 손상 시키거나 기능 전환을하지 않도록보다 안정적이고 (또는 빌드를 중단) 프로그램을 더주의해서 강요합니다.

CI를 이런 식으로 또는 그런 식으로 수행 할 때 장단점이 있지만 문제의 범위를 벗어납니다 ( 관련 질문 참조 ). 원한다면 소규모 개발자 팀이 기능 브랜치에서 함께 작업합니다. 한 개발자가 해당 분기의 빌드를 중단시키는 무언가를 커밋하면 CI 시스템이 커밋을 되돌려 야합니까?


38
실패한 빌드는 master시작에 도달해서는 안됩니다 . 바로 개발 및 기능 분기가 사용되는 것입니다. 그런 다음 이러한 변경 사항은 통합 지점과 같은 방식으로 진행되어 여러 개발자의 모든 새로운 기능이 함께 작동하는지 테스트 할 수 있으며 테스트 된 경우에만 마스터로 들어갈 수 있습니다. 아니면 적어도 하나의 가능한 워크 플로입니다.
Thorsten Müller

1
@ thorstenmüller는 모든 개발자가 사용하는 개발 브랜치에 있다고 생각합니다. CI 시스템이 빌드에 실패한 커밋을 되돌려 야합니까?
Carlos Campderrós

7
이상한 방법으로 git을 사용하고있는 것 같습니다. 일반적으로 사람들은 자신의 지점에서 자체 리포지토리를 작업해야하며, 개인 빌드를 위해 CI가 변경 사항을 확인한 후에 만 ​​주 서버로 푸시해야합니다.
Wilbert

4
> "이 충돌은 최소로 줄어 듭니다"; 병합시 충돌이 줄어드는 반면 잘못된 병합 문제는 더 많이 발생합니다. 해결책은 브랜치가 아닌 프로세스의 일부로 마스터에서 브랜치로 지속적으로 병합하는 것입니다.
deworde

2
... 실패한 빌드가 마스터로 시작되지 않는 이유는 무엇입니까?
user253751

답변:


55

나는 다음과 같은 이유로 이것을하지 않을 것입니다 :

  • 귀하를 대신하여 코드변경 하기 위해 자동화 된 도구를 설정할 때마다 도구가 잘못 될 위험이 있거나 변경을 중지해야하는 상황이 발생할 수 있습니다 (예 : 최신 버전의 Google Mock 버그가 있었으므로 코드가 실패하지 않았으므로 재구성하는 데 시간을 낭비해야합니다. 또한 코드의 버그가 아니라 빌드 시스템의 버그로 인해 빌드가 실패 할 위험이 항상 있습니다. 저에게 CI는 제 코드 가 정확 하다는 확신을 얻습니다 . 이것은 단지 내가 걱정할 다른 잠재적 인 문제의 근원으로 바꾸어 놓을 뿐이다.

  • "빌드"를 망가 뜨리는 버그의 종류는 수정하는 데 시간이 거의 걸리지 않는 어리석은 실수 여야 합니다 (의견에서 언급했듯이 이는 사실입니다). 더 미묘하고 복잡한 버그가 정기적으로 마스터에 적용되는 경우 올바른 해결책은 "더 빨리 수정"하지 않는 것입니다. 기능 분기가 병합되기 전에 검토 할 때 더 신중해야합니다.

  • 버그가 올바르게 수정되는 동안 몇 분 동안 마스터를 빌드 할 수없는 상태로두면 아무도 해치지 않습니다. CEO가 개인적으로 마스터를 체크 아웃하고 임의의 순간에 고객에게 직접 코드를 게시하는 것은 아닙니다. 당신이 버그를 수정하기 전에 뭔가를 공개 할 필요가있는 매우 드문 경우, 다음 을 쉽게 게시하기 전에 수동으로 복귀 할 수있는 결정을 내릴 수 있습니다.


1
또한 성공적인 빌드 만 배포 할 수있는 "빌드 드롭"생성을 트리거해야합니다. 빌드가 실패하면 배포 가능한 빌드 드롭이 없어야하므로 누군가가 잘못된 코드를 클라이언트에 게시 할 위험이 없습니다.
Mark Freedman

1
내가 생각하는 것보다 많이 사용되고 더 나은 다른 옵션이 있습니다. (우리는 트위터에서 사용합니다). 마스터에 실패한 빌드를 넣지 말고 바보 같은 실수도 여전히 쉽게 고칠 수 있습니다. 아래의 전체 답변을 참조하십시오.
Dean Hiller

26

먼저 조건에 동의합시다.

개인적으로 Continuous Build와 Continuous Integration이라는 용어를 사용하여 두 가지 시나리오를 구분합니다.

  • 연속 빌드 : 마지막 빌드 이후에 리포지토리가 변경되었는지 주기적으로 확인하여 빌드 / 테스트했는지 확인하는 도구입니다.
  • 지속적인 통합 : 풀 요청을 가져 와서 최신 헤드에 대해 확인 하기 전에 이를 확인하는 도구입니다 .

후자 인 Continuous Integration은 보호하는 저장소가 항상 녹색 1 임을 의미합니다 . 엄밀히 더 좋습니다.

귀하의 질문은 Continuous Build에 대해서만 의미가 있으므로 이것이 귀하의 설정이라고 가정합니다.

1 : 환경 적 원인으로 인해 빌드가 중단 될 수 있습니다. 예를 들어 하드 코딩 된 연도 (2015) 테스트는 2016 년 1 월에 실패하기 시작하고 디스크가 가득 찼을 수 있습니다 ... 물론 불안정의 재앙이 있습니다. 테스트. 나는이 문제들을 거만하게 무시한다. 그렇지 않으면 우리는 어디에도 가지 못할 것입니다.


연속 빌드 설정이있는 경우 실제로 빌드를 손상시킬 수있는 커밋의 반전을 자동화 할 수 있지만 몇 가지 미묘한 부분이 있습니다.

  • 실제로 커밋을 제거 할 수는 없습니다. 다른 동료가 이미 커밋을 확인했을 수 있으며 다음에 커밋을 시도 할 때 다시 커밋합니다. 대신, 반전은 차이를 커밋해야합니다 . 아, 그리고 동료들은 그들이 다시 되돌릴 수있는 방법을 찾아야하므로 그들이 정확했을 때 자신의 작업을 되 돌리는 것에 대해 당신을 미워할 것입니다 ...
  • 실제로 마지막 커밋을 제거 할 수는 없지만 (병합입니다) 모든 커밋을 제거해야합니다 ... 특정 지점까지. 예를 들어, 마지막으로 알려진 올바른 커밋 (시스템을 부팅 할 때주의하십시오).
  • 외부 원인 (환경 문제)에 대해 생각하고 모든 것을 0 일로 되 돌리는 설정을 피해야합니다. 고맙게도, 마지막으로 성공한 커밋으로 되 돌리면이 문제가 발생합니다.
  • 마지막으로 성공한 빌드가 더 이상 빌드되지 않을 수 있다고 생각해야합니다 (환경 문제).이 경우 추가 커밋이 모두 취소 될 수 있습니다. 이상적으로는 실패한 경우, 되돌리기 전에 마지막으로 성공한 빌드를 체크 아웃하고 다시 테스트하는 것이 가장 좋습니다. 통과하면 되돌 리거나 그렇지 않으면 경고를 발생시킵니다.

이 시스템을 사용하면 불안정한 테스트 또는 동료가 종종 쓰레기를 저지르는 경우 많은 좋은 커밋이 취소됩니다. 그러면 동료가 당신을 미워할 것입니다.


바라건대 내 공포 이야기가 손상된 저장소를 허용하는 문제를 폭로했기 때문에 이제 PR이 저장소로 직접 푸시되지 않고 대신 작업 대기열에서 병합하기 위해 대기하고 한 번에 하나씩 통합되는 적절한 Continuous Integration 파이프 라인을 구현하게됩니다 ( 또는 롤업으로) :

  • 로컬 리포지토리 헤드 가져 오기
  • 풀 요청 적용
  • 구축 및 테스트
  • 성공한 경우 리포지토리로 푸시, 그렇지 않으면 실패로 표시
  • 다음 요청으로 이동

두 가지를 모두 시도한 후에는 이것이 더 좋습니다.


2
이것은 정답입니다. 올바른 해결책은 나쁜 변화가 마스터 지점에 도달하지 못하도록 막고, 착륙하지 못하게하고 롤백을 처리해야합니다.
Daniel Pryden

여기서 문제는 "다른 개발자들로부터 당신을 격리시키는 그들의 명시된 비용과 그 변화"가 이점을 능가한다고 생각하는 것입니다. 명시된 비용은 두 사람이 더 많이 갈라질수록 사소한 합병의 위험이 증가한다는 것입니다. IMO는 깨진 코드로부터 격리되는 이점이 분명합니다. 질문자는 깨진 코드를 간단하게 가져올 수있는 "낙관적"전략을 세우고 master테스트가 실패하면이 상황을 해결하려고합니다. 다른 모든 사람들은 조언대로 "비관적"전략을 취하고 전달 코드 만 사용할 수있게합니다.
Steve Jessop

( "풀을 사용할 수 있음"이란, "풀에서 master"을 의미합니다. 이상적으로는 개발자가 고의적으로 할 수있는 일이지만 master테스트 및 통과 전에 커밋을 지연시켜야합니다 . 개발자가 원하는 경우 테스트되지 않았거나 테스트 및 실패한 코드를 잘 선택하십시오. 그런 의미에서 코드를 "사용할 수"있습니다.
Steve Jessop

올바른 해결책은 나쁜 변경이 모든 지점에 도달하지 않도록하는 것입니다. 실패한 커밋은 절대 공개되지 않아야합니다.
Miles Rout

5

이것이 모범 사례입니까, 아니면 개발자가 고칠 때까지 마스터를 깨뜨리는 것보다 문제가 될 수 있습니까?

문제가 있습니다. "마스터 HEAD가 고장났습니다. 나는 최고 변화를 되돌릴 것입니다"라고 결정하는 사람은 CI 시스템과 완전히 다릅니다.

몇 가지 단점이 있습니다.

  • 자동 반전 프로세스의 오류로 인해 저장소가 손상 될 수 있습니다.

  • 이것은 단일 변경 세트 (맨 위)가 빌드를 망친 것으로 가정합니다 (비현실적 임)

  • 관리자는 조사와 커밋보다 문제를 해결하기 위해 더 많은 노력을 기울여야합니다 (역사 기록도 살펴 봐야 함)

브랜치에 대한 커밋은 다른 개발자 및 변경 사항을 차단하고 브랜치를 다시 통합하고 가능한 충돌을 처리해야 할 때 시간을 추가하기 때문에 브랜치 개념은 실제 CI와 반대되는 것으로 생각합니다.

이 신념 (지점 대 CI)이 올바르지 않습니다. 단위 테스트 된 변경 세트 만 커밋 하는 하나의 안정적인 브랜치를 유지하십시오 . 나머지 (기능 지점 및 지역 지점)는 각 개발자의 책임이며 CI 정책의 일부가 아닙니다.

기능 분기에서는 다른 개발자와 격리 하려고 합니다. 이를 통해 다음을 수행 할 수 있습니다.

  • 탐색 적 코딩 수행

  • 코드베이스로 실험

  • 부분 커밋 (효과적으로 작동하지 않는 코드 커밋)을 수행하여 백업 지점을 설정하고 (고정 된 경우) 커밋 메시지를 통해 더 의미있는 전체 변경 기록을 작성하고 작업을 백업하고 다른 작업으로 완전히 전환 ( "git commit && git checkout")을 쓰는 데 걸리는 시간

  • 시간이 오래 걸리는 우선 순위가 낮은 작업 수행 (예 : 데이터 계층의 모든 80 개 클래스를 변경하는 리팩토링을 수행하려는 경우 : 하루에 두 개씩 변경하고 코드가 컴파일 될 때까지 변경 함) 단일 커밋을 할 때까지 다른 사람에게 영향을 미치지 않습니다.

한 개발자가 해당 분기의 빌드를 중단시키는 무언가를 커밋하면 CI 시스템이 커밋을 되돌려 야합니까?

해서는 안됩니다. CI 지점에서 안정적인 코드를 커밋하는 것은 자동화 시스템이 아닌 커미터의 책임입니다.


2

Gerrit + Jenkins 환경을 사용하여 마스터 브랜치를 항상 좋은 상태로 유지하는 것이 좋습니다. 사람들은 새 코드를 Gerrit로 푸시하여 Jenkins 작업을 시작하여 해당 패치, 빌드, 테스트 등을 수행합니다. 패치 및 Jenkins와 같은 다른 개발자가 작업을 성공적으로 완료하면 Gerrit은 해당 코드 조각을 마스터 지점에 병합합니다.

@ brian-vandenberg가 설명한 비슷한 환경

브랜치를 양호한 상태로 유지하는 것 외에도 소프트웨어에 대한 코드 품질 및 지식 공유를 향상시키는 코드 검토 단계를 추가합니다.

[1] 젠킨스 https://jenkins-ci.org/

[2] Gerrit https://www.gerritcodereview.com/


1

CI는 리포지토리의 커밋 히스토리를 변경해서는 안됩니다.

여기서 올바른 솔루션은 테스트 및 검증되지 않은 경우 커밋을 마스터 브랜치에 추가하지 않는 것입니다.

기능 분기에서 작업하고 CI에서 자동으로 CI를 실행하고 빌드에 실패한 경우이를 마스터로 병합하지 마십시오.

기능 분기에서 실행하고 빌드 / 마스터 / 통합 / 로컬 분기에 로컬 분기로 병합 한 다음 테스트를 실행하여 문제가 우려되는 경우 테스트를 병합하는 추가 빌드를 가질 수 있습니다.


1
이것은 어떤 식 으로든 질문에 대답하지 않습니다. 기능 분기에서 빌드가 실패하면 CI가 커밋을 되돌려 야합니까?
Carlos Campderrós

기능 분기에서 빌드가 성공하지만 병합 후에 실패하면 어떻게됩니까?
Matthieu M.

@MatthieuM. 병합은 커밋입니다. 병합하는 CI 단계가 빌드를 되돌려 야합니까?
Carlos Campderrós

@ CarlosCampderrós : 나는 개인적으로 커밋을 되돌리려는 설정을 하지 않을 것이다. 너무 복잡합니다.
Matthieu M.

나는 의견을 언급했다.
Daenyth

1

우리는 빌드 서버에 Jenkins를 사용하고 커밋을 푸시하기 위해 게이트 키퍼 모델을 사용합니다. 여기서 Jenkins와 커밋 트리거 (피어 리뷰어가 작업을 수행했는지 확인)가 게이트 키퍼입니다.

커밋은 을 통해 Jenkins에게 간접적으로 푸시 되며 마스터 리포지토리를 복제 한 다음 커밋을 가져와 병합하고 필요한 모든 빌드를 수행합니다 (Linux / Solaris). 모든 빌드가 완료되면 커밋이 푸시됩니다.

이것은 지금까지 논의 된 모든 문제가 아니라면 많은 것을 피합니다.

  • 역사 변경
  • 파손을 해결 해야하는 개발자라면 역사를 올바르게 얻는 것
  • (빌드 빌드 형태의) 불안정성은 결코 도입되지 않습니다

또한 단위 테스트 완료와 같은 다른 요구 사항을 직접 시행 할 수도 있습니다.


다시 : downvote, 당신은 내 대답에 대해 마음에 들지 않는 것에 대해 의견을 말 하시겠습니까?
브라이언 반덴버그

0

마지막 커밋이 빌드를 중단했다는 자동 이메일을 몇 번이나 받았습니까? 몇 번 잘못 되었습니까? 그러나 지금 당신은 그것이 진짜 당신인지 또는 같은 시간에 다른 커밋을 한 다른 사람인지 확인해야합니다. 아니면 환경적인 것일 수도 있습니다.

시스템이 확실하지 않으면 확실히 자동화하고 싶지 않습니다.


0

묻는 질문에 결함이 있습니다. 그래도 나는이 진술을 존중한다

"지점에 커밋하면 다른 개발자 및 변경 사항으로부터 격리되므로 브랜치의 개념은 실제 CI와 상충된다고 생각합니다."

당신이해야 할 일은이 단계입니다

  • 원하는 경우 마스터에서 일하십시오 (괜찮고 모든 사람에게서 변경 사항을 계속 가져옵니다).하지만 로컬로 마스터하지는 않습니다.
  • 변경 사항을 마스터에 커밋하기 전에 submit_XXXXXX로 지점을 만드십시오.
  • 자동 빌드에서 모든 submit_XXX 분기 빌드를 선택하십시오.
  • 옵션 1 : 나누기 또는 병합 나누기 ... 변경이 거부되었으며 절대 마스터에 도달하지 않습니다.
  • 옵션 2 : 빌드 작업, 젠킨스가 마스터를 푸시하고 업데이트

그렇다면 우리가하는 일은 모두가 실제로 마스터에 커밋하는 것을 막기 위해 git commit hook을 넣는 것입니다. 그것은 잘 작동합니다 .... 깨진 빌드가 없으며 마스터의 되돌리기 커밋도 없습니다.

나중에, 딘

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.