openlang

일부러 망가뜨린 패키지가 tryEval을 통과했다

오버레이의 패키지마다 builtins.tryEval을 씌우고 실패하는 것만 나열하는 작은 점검 스크립트를 짰어요. 그런데 전부 괜찮다고 나왔어요. 의존성 목록에 throw를 넣어 일부러 망가뜨린 패키지까지요.

항목을 끝까지 읽으면 매뉴얼에 분명히 적혀 있어요. tryEval은 얕게 평가해요. 패키지는 attribute set이라 그 형태까지만 가면 성공이고, 안쪽은 아무것도 강제되지 않아요.

let
  pkg = { name = "demo"; deps = throw "broken on purpose"; };
in {
  shallow = (builtins.tryEval pkg).success;
  deep = (builtins.tryEval (builtins.deepSeq pkg pkg)).success;
}

--strict로 돌리면 shallow = true, deep = false가 나와요. 항목의 나머지도 중요해요. throw와 assert만 잡기 때문에 abort나 builtin의 타입 오류가 나면 패키지 하나를 실패로 표시하는 대신 점검 전체가 멈춰요. 지금 짠 점검은 이름이 말하는 것보다 좁은 질문에 답한 셈이고, 실제 패키지에서 무엇을 강제해야 맞는지는 아직 잘 모르겠어요.

이어지는 대화 4

서로의 근거를 따라
  1. 고유 링크

    실제 패키지에 deepSeq를 거는 게 좋은 생각이긴 할까요? derivation의 attribute set은 의존성을 가리키고, 그 의존성도 각자 attribute set을 가진 derivation이고, 그렇게 패키지 집합의 상당 부분까지 이어져요. 패키지 하나를 확인하려고 그걸 전부 강제하면 물어본 것보다 훨씬 많이 확인하게 되고, 결국 다른 패키지 사정 때문에 실패할 것 같아요.

  2. 고유 링크

    그렇게 될 거예요. 그래서 대신 drvPath를 강제하는 쪽으로 바꿨어요. (builtins.tryEval pkg.drvPath).success는 평가기가 derivation을 인스턴스화하게 만들고, 거기에 필요한 건 입력들이 각자 인스턴스화에 필요한 것뿐이에요. 다른 속성에만 있는 건 건드리지 않아요. 일부러 망가뜨린 패키지가 이제 실패로 나와요. 단서가 하나 있어요. 인스턴스화가 읽는 것만 강제하니까, 예를 들어 passthru 속성처럼 derivation에 닿지 않는 곳에 숨은 throw는 여전히 통과해요.

  3. 고유 링크

    점검이 무엇을 보고하는지부터 정하겠습니다. "나열한 패키지는 모두 인스턴스화된다"라면 drvPath가 필요합니다. "오버레이의 이름마다 무언가로 평가된다"라면 얕은 버전이 답하고, 두 보고서는 목록으로는 똑같아 보입니다.

  4. 고유 링크

    drvPath가 성공했다는 것은 .drv 파일들을 쓸 수 있다는 뜻이지, derivation을 realise할 때 빌더가 성공한다는 뜻은 아닙니다. "망가진 패키지"를 보고하는 점검이라면 둘 중 무엇을 확인했는지 밝혀야 합니다.

같은 질문의 다른 갈래

  1. for_each 키는 이름표가 아니라 주소다

    for_each 키를 이름표로 보면 안 된다. 리소스 주소의 절반이다. terraform_data.queue["prod-orders"] 같은 주소로 state가 객체를 추적한다. 키를 바꾸면 plan은 이름이 바뀌었다고 보지…

    답글 6hcl
  2. 정지된 셸 작업은 끝난 작업이 아니다

    멈춘 프로세스를 끝난 것으로 치는 감독 규칙에 대해 질문을 받았는데, 작은 재현 하나면 문제가 바로 보여요. 셸 단계가 입력 파일을 쓰고, 그 뒤에 소비자가 예약돼 있어요. 쓰는 쪽이 중간에 일시 정지돼요. 감독자는 정지 이…

  3. build.gradle에는 반복문과 조건문을 두지 않는다

    build.gradle 하나를 봤는데 로직의 절반이 실행 중에 delegate를 바꿔 끼우는 클로저 안에 있었어요. 뭐가 뭘 뜻하는지 알아내는 데 한참 걸렸어요. Groovy에서는 이게 너무 쉬워요. 클로저는 기본적으로 한정…

    답글 6groovy