RuboCop 규칙 개발 가이드라인
GitLab v19.1코드베이스 스타일은 RuboCop으로 정의하고 적용합니다. bundle exec rubocop --parallel 명령으로 로컬에서 위반 사항을 확인할 수 있습니다. 또한 Solargraph gem을 사용하여 지원되는 IDE에 RuboCop을 통합할 수 있습니다.
코드베이스 스타일은 RuboCop으로 정의하고 적용합니다.
bundle exec rubocop --parallel 명령으로 로컬에서 위반 사항을 확인할 수 있습니다.
CI에서는 static-analysis job이 자동으로 이를 검사합니다.
또한 Solargraph gem을 사용하여 지원되는 IDE에 RuboCop을 통합할 수 있습니다.
아직 결정을 내리지 않은 RuboCop 규칙에 대해서는 Ruby 스타일 가이드를 따라 관용적인 Ruby를 작성하세요.
리뷰어/메인테이너는 스타일에 대해 관대하게 접근하고 지나치게 엄격하지 않아야 합니다.
일부 RuboCop 규칙은 비활성화되어 있으며, 이 경우 리뷰어/메인테이너는 저자에게 어느 한 스타일을 사용하도록 요청해서는 안 됩니다. 두 가지 스타일 모두 허용되기 때문입니다. 이는 bike-shedding의 여지를 남기기 때문에 이상적인 상황은 아닙니다. 이상적으로는 스타일 관련 토론, 사소한 지적, 혹은 리뷰에서의 불필요한 반복을 피하기 위해 모든 RuboCop 규칙을 활성화해야 합니다. GitLab Ruby 스타일 가이드에는 리뷰에서 자주 언급되지만 강제되지 않는 스타일의 비포괄적 목록이 포함되어 있습니다.
또한 테스트 전용 스타일 가이드 및 모범 사례도 별도로 제공됩니다.
인라인 규칙 비활성화#
기본적으로 RuboCop 규칙은 인라인 비활성화를 사용하지 않아야 합니다. 인라인 비활성화는 코드베이스에 적용하려는 합의된 코드 표준을 무효화하기 때문입니다.
인라인 비활성화를 반드시 사용해야 한다면, 규칙이 비활성화된 같은 줄에 코드 주석으로 이유를 제공하세요.
이 인라인 비활성화 주석 위에 추가 컨텍스트를 코드 주석으로 작성할 수 있습니다. 상세한 컨텍스트를 제공하기 위해 verbose한 코드 주석 대신 리소스(이슈, 에픽 등)로 연결하는 링크를 사용하세요.
임시 인라인 비활성화에는 rubocop:todo를 사용하고 후속 이슈 또는 에픽을 링크하세요.
예시:
# bad
module Types
module Domain
# rubocop:disable Graphql/AuthorizeTypes
class SomeType < BaseObject
if condition # rubocop:disable Style/GuardClause
# more logic...
end
object.public_send(action) # rubocop:disable GitlabSecurity/PublicSend
end
# rubocop:enable Graphql/AuthorizeTypes
end
end
# good
module Types
module Domain
# rubocop:disable Graphql/AuthorizeTypes -- already authorized in parent entity
class SomeType < BaseObject
if condition # rubocop:todo Style/GuardClause -- Cleanup via https://gitlab.com/gitlab-org/gitlab/-/issues/1234567890
# more logic...
end
# At this point `action` is safe to be used in `public_send`.
# See https://gitlab.com/gitlab-org/gitlab/-/issues/123457890.
object.public_send(action) # rubocop:disable GitlabSecurity/PublicSend -- User input verified
end
# rubocop:enable Graphql/AuthorizeTypes
end
end
새 RuboCop cop 생성#
일반적으로 린팅 규칙을 프로그래밍 방식으로 적용하는 것이 앞서 언급한 bike-shedding을 줄이는 데 더 효과적입니다.
이를 위해 코드베이스에 새로운 RuboCop 규칙을 생성하는 것을 권장합니다.
특정 스타일을 적용하기 위해 새 cop을 추가하기 전에 팀과 논의하세요.
저희는 여러 Ruby 코드베이스에서 cop을 관리하며, 모든 cop이 GitLab 애플리케이션에만 특정한 것은 아닙니다.
여러 애플리케이션에 적용할 수 있는 새 cop을 생성할 때는 gitlab-styles gem에 추가하는 것을 권장합니다.
cop이 메인 GitLab 애플리케이션에만 적용되는 규칙을 타깃으로 한다면, GitLab에 추가해야 합니다.
Cop 유예 기간#
cop의 TODO YAML 설정에 Details: grace period가 정의되어 있고 활성화된 경우, 해당 cop은 유예 기간에 있습니다.
기본 브랜치에서 유예 기간에 있는 cop의 위반은 RuboCop CI job을 실패시키지 않습니다. 대신 job이 #f_rubocop Slack 채널에 알림을 보냅니다. 그러나 다른 브랜치에서는 RuboCop job이 실패합니다.
Slack의 #f_rubocop 채널에서 1주일간 경고가 없으면 유예 기간을 안전하게 해제할 수 있습니다.
TODO를 생성할 때 다음 조건에서 RuboCop cop 규칙이 유예 기간에 배치됩니다:
-
이전에 유예 기간에 있었던 규칙
-
새로 추가된 규칙
-
마지막 생성 이후 규칙 위반 수가 증가한 경우
새 cop 또는 cop 변경 제안#
새 cop을 적용하거나 기존 cop 설정을 변경하는 제안을 하려면, 규칙을 추가할 위치에 따라 gitlab-styles 머지 리퀘스트 템플릿 또는 gitlab 머지 리퀄스트 템플릿을 사용하세요. 이 템플릿을 사용하면 모든 메인테이너가 선호하는 스타일에 대한 피드백을 제공하도록 장려하고, 새 규칙의 결과를 소통하는 구조화된 방식을 제공합니다.
새 cop 활성화#
-
.rubocop.yml에서 새 cop을 활성화합니다(gitlab-styles를 통해 이미 완료되지 않은 경우). -
TODO를 수정하는 이슈를 생성하고 커뮤니티 기여를 장려합니다(~"quick win" 및/또는 ~"Seeking community contributions" 라벨 사용). 예시를 참고하세요.
-
#f_rubocopSlack 채널에서 1주일간 조용한 기간 후grace period를 제거하는 이슈를 생성합니다. 예시를 참고하세요.
침묵된 위반#
유예 기간에 있는 cop에 대한 위반이 침묵 처리되면, #f_rubocop Slack 채널에 2시간마다 알림 메시지가 전송됩니다.
이 문제를 해결하려면:
-
링크된 CI job에서 침묵된 위반이 있는 cop을 찾습니다.
-
해당 cop에 대한 TODO를 생성합니다.
RuboCop 노드 패턴#
Ruby의 AST를 매칭하기 위한 노드 패턴을 생성할 때 scripts/rubocop-parse를 사용할 수 있습니다.
이 도구는 Ruby 표현식의 AST를 표시하여 매처를 생성하는 데 도움을 줍니다.
!97024도 참고하세요.
RuboCop 예외 해결#
RuboCop 예외 수가 기본 exclude-limit 15를 초과하면, 여러 커밋에 걸쳐 예외를 해결할 수 있습니다. 혼란을 최소화하기 위해 예외 목록을 통해 진행 상황을 추적해야 합니다.
초기 목록 또는 특정 RuboCop 규칙의 목록을 생성하는 권장 방법은 Rake 태스크 rubocop:todo:generate를 실행하는 것입니다:
# Initial list
bundle exec rake rubocop:todo:generate
# List for specific RuboCop rules
bundle exec rake 'rubocop:todo:generate[Gitlab/NamespacedClass,Lint/Syntax]'
이 Rake 태스크는 .rubocop_todo/에 예외 목록을 생성하거나 업데이트합니다. 예를 들어, RuboCop 규칙 Gitlab/NamespacedClass의 설정은 .rubocop_todo/gitlab/namespaced_class.yml에 위치합니다.
Rake 태스크 실행 후 .rubocop_todo/의 변경 사항을 반드시 커밋하세요.
주기적 RuboCop todo 파일 생성#
코드 변경으로 인해 일부 RuboCop 위반이 시간이 지남에 따라 자동으로 수정됩니다. 이러한 위반이 재도입되는 것을 방지하기 위해 주기적으로 .rubocop_todo 파일을 재생성합니다.
이를 위해 housekeeper gem을 사용합니다.
이 gem은 .rubocop_todo 파일을 재생성하고 머지 리퀘스트를 생성합니다.
생성된 머지 리퀘스트를 검토하기 위해 리뷰어가 무작위로 배정됩니다.
로컬에서 keep을 실행하려면 다음 단계를 따르고 bundle exec gitlab-housekeeper -k Keeps::GenerateRubocopTodos를 실행하세요.
기존 RuboCop 예외 표시#
.rubocop_todo/**/*.yml을 통해 제외된 코드의 기존 RuboCop 예외를 표시하려면, 환경 변수 REVEAL_RUBOCOP_TODO를 1로 설정하세요.
이를 통해 일상적인 작업 중에 기존 RuboCop 예외를 드러내고 함께 수정할 수 있습니다.
Include 및 영구 Exclude는 .rubocop_todo/**/*.yml 대신 .rubocop.yml에 정의하세요.
RuboCop 문서#
내부 RuboCop 규칙을 생성할 때는 RDoc 스타일의 문서를 포함해야 합니다.
이 문서는 Hugo를 사용하여 정적 사이트를 생성하는 데 사용되며, https://gitlab-org.gitlab.io/gitlab/rubocop-docs/에 게시됩니다.
이 사이트에는 gitlab 및 gitlab-styles 프로젝트의 모든 내부 cop이 "good" 및 "bad" 예시와 함께 포함됩니다.