SCM Provider Generator

SCM Provider Generator

SCMaaS provider(예: GitHub)의 API를 사용해 조직 내 리포지토리를 자동으로 발견하는 generator예요. 마이크로서비스를 여러 리포지토리에 분산하는 GitOps 레이아웃 패턴과 잘 맞아요.

출처: 문서

본문

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
  - scmProvider:
      # Which protocol to clone using.
      cloneProtocol: ssh
      # See below for provider specific options.
      github:
        # ...
  • cloneProtocol: SCM URL에 사용할 프로토콜. 기본값은 provider별이지만 가능하면 ssh. 모든 provider가 반드시 모든 프로토콜을 지원하는 것은 아니므로 사용 가능한 옵션은 아래 provider 문서를 참고하세요.

[!NOTE] SCM generator 사용의 보안 영향을 알아두세요. 시크릿 유출을 피하려면 관리자만 ApplicationSet을 생성할 수 있고, SCM generator가 있는 ApplicationSet의 project 필드가 템플릿화되어 있다면 경계 밖 리소스 관리가 부여되는 것을 피하려면 관리자만 repo/branch를 생성할 수 있어요.

프록시 구성 (Proxy Configuration)

ApplicationSet 컨트롤러가 HTTP/HTTPS 프록시를 통해 SCM provider API(GitHub, GitLab, Gitea, Bitbucket Server)에 도달해야 한다면 전용 SCM 프록시 플래그를 사용하세요:

argocd-applicationset-controller \
  --scm-proxy-url=http://proxy.corp.example.com:3128 \
  --scm-no-proxy=internal.gitlab.corp.example.com,10.0.0.0/8

이 플래그들은 환경 변수로도 설정할 수 있어요:

  • ARGOCD_APPLICATIONSET_CONTROLLER_SCM_PROXY_URL
  • ARGOCD_APPLICATIONSET_CONTROLLER_SCM_NO_PROXY

[!NOTE] --scm-proxy-url은 아웃바운드 SCM API 요청에만 영향을 줘요. Kubernetes API 서버 연결에는 영향을 주지 않아요. Kubernetes API 트래픽을 프록시하려면 --proxy-url(표준 kubectl 플래그)을 사용하세요.

GitHub

GitHub 모드는 GitHub API를 사용해 github.com 또는 GitHub Enterprise에서 조직을 스캔해요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
  - scmProvider:
      github:
        # The GitHub organization to scan.
        organization: myorg
        # For GitHub Enterprise:
        api: https://git.example.com/
        # If true, scan every branch of every repository. If false, scan only the default branch. Defaults to false.
        allBranches: true
        # Exclude repos that are archived
        excludeArchivedRepos: true
        # Reference to a Secret containing an access token. (optional)
        tokenRef:
          secretName: github-token
          key: token
        # (optional) use a GitHub App to access the API instead of a PAT.
        appSecretName: gh-app-repo-creds
  template:
  # ...
  • organization: 스캔할 GitHub 조직의 필수 이름. 여러 조직이 있으면 여러 generator를 사용하세요.
  • api: GitHub Enterprise를 사용한다면, 접근할 URL.
  • allBranches: 기본값(false)에서 템플릿은 각 repo의 기본 브랜치에 대해서만 평가돼요. true이면 모든 리포지토리의 모든 브랜치가 필터로 전달돼요. 이 플래그를 사용한다면 branchMatch 필터를 사용하고 싶을 거예요.
  • tokenRef: 요청에 사용할 GitHub 접근 토큰을 담고 있는 Secret 이름과 키. 지정하지 않으면 익명 요청을 하며, 이는 더 낮은 rate limit을 갖고 공개 리포지토리만 볼 수 있어요.
  • appSecretName: repo-creds 형식의 GitHub App 시크릿을 담고 있는 Secret 이름.
  • excludeArchivedRepos: 보관된(archived) 리포지토리를 제외. 기본값 false

라벨 필터링에는 리포지토리 토픽이 사용돼요.

사용 가능한 clone 프로토콜은 sshhttps예요.

Gitlab

GitLab 모드는 GitLab API를 사용해 gitlab.com 또는 자체 호스팅 GitLab에서 조직을 스캔해요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
  - scmProvider:
      gitlab:
        # The base GitLab group to scan.  You can either use the group id or the full namespaced path.
        group: "8675309"
        # For self-hosted GitLab:
        api: https://gitlab.example.com/
        # If true, scan every branch of every repository. If false, scan only the default branch. Defaults to false.
        allBranches: true
        # If true, recurses through subgroups. If false, it searches only in the base group. Defaults to false.
        includeSubgroups: true
        # If true and includeSubgroups is also true, include Shared Projects, which is gitlab API default.
        # If false only search Projects under the same path. Defaults to true.
        includeSharedProjects: false
        # Include repos that are archived
        includeArchivedRepos: true
        # filter projects by topic. A single topic is supported by Gitlab API. Defaults to "" (all topics).
        topic: "my-topic"
        # Reference to a Secret containing an access token. (optional)
        tokenRef:
          secretName: gitlab-token
          key: token
        # If true, skips validating the SCM provider's TLS certificate - useful for self-signed certificates.
        insecure: false
        # Reference to a ConfigMap containing trusted CA certs - useful for self-signed certificates. (optional)
        caRef:
          configMapName: argocd-tls-certs-cm
          key: gitlab-ca
  template:
  # ...
  • group: 스캔할 기본 GitLab 그룹의 필수 이름. 기본 그룹이 여러 개면 여러 generator를 사용하세요.
  • api: 자체 호스팅 GitLab을 사용한다면, 접근할 URL.
  • allBranches: 기본값(false)에서 템플릿은 각 repo의 기본 브랜치에 대해서만 평가돼요. true이면 모든 리포지토리의 모든 브랜치가 필터로 전달돼요. 이 플래그를 사용한다면 branchMatch 필터를 사용하고 싶을 거예요.
  • includeSubgroups: 기본값(false)에서 컨트롤러는 기본 그룹의 repo만 직접 검색해요. true이면 모든 하위 그룹을 재귀하며 스캔할 repo를 찾아요.
  • includeSharedProjects: true이고 includeSubgroups도 true이면 Shared Projects를 포함하며, 이는 gitlab API 기본값이에요. false이면 같은 경로 아래의 Projects만 검색해요. 일반적으로 대부분은 false로 설정된 동작을 원할 거예요. 기본값 true.
  • includeArchivedRepos: 보관된 리포지토리를 포함. 기본값 false
  • topic: topic으로 프로젝트를 필터링. Gitlab API는 단일 topic을 지원해요. 기본값 "" (모든 토픽).
  • tokenRef: 요청에 사용할 GitLab 접근 토큰을 담고 있는 Secret 이름과 키. 지정하지 않으면 익명 요청을 하며, 이는 더 낮은 rate limit을 갖고 공개 리포지토리만 볼 수 있어요.
  • insecure: 기본값(false) - SCM 인증서의 유효성 확인 건너뜀 - 자체 서명 TLS 인증서에 유용.
  • caRef: 신뢰할 GitLab 인증서를 담고 있는 선택적 ConfigMap 이름과 키 - 자체 서명 TLS 인증서에 유용. 신뢰할 인증서를 보유한 ArgoCD CM을 참조할 수 있음.

라벨 필터링에는 리포지토리 토픽이 사용돼요.

사용 가능한 clone 프로토콜은 sshhttps예요.

자체 서명 TLS 인증서 (Self-signed TLS Certificates)

insecure를 true로 설정하는 것보다 선호할 만한 대안으로 Gitlab용 자체 서명 TLS 인증서를 구성할 수 있어요.

ApplicationSet의 SCM / PR Gitlab Generator가 자체 서명 TLS 인증서를 사용하려면 인증서가 applicationset-controller에 마운트되어야 해요. 마운트된 인증서 경로는 환경 변수 ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH 또는 매개변수 --scm-root-ca-path로 명시적으로 설정해야 해요. applicationset 컨트롤러는 마운트된 인증서를 읽어 SCM/PR Provider용 Gitlab 클라이언트를 만들어요.

이것은 argocd-cmd-params-cm ConfigMap에 applicationsetcontroller.scm.root.ca.path를 설정하면 편리하게 달성돼요. 이 값을 설정한 후 ApplicationSet 컨트롤러를 재시작하세요.

Gitea

Gitea 모드는 Gitea API를 사용해 인스턴스의 조직을 스캔해요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
  - scmProvider:
      gitea:
        # The Gitea owner to scan.
        owner: myorg
        # The Gitea instance url
        api: https://gitea.mydomain.com/
        # If true, scan every branch of every repository. If false, scan only the default branch. Defaults to false.
        allBranches: true
        # Exclude repos that are archived
        excludeArchivedRepos: true
        # Reference to a Secret containing an access token. (optional)
        tokenRef:
          secretName: gitea-token
          key: token
  template:
  # ...
  • owner: 스캔할 Gitea 조직의 필수 이름. 여러 조직이 있으면 여러 generator를 사용하세요.
  • api: 사용 중인 Gitea 인스턴스의 URL.
  • allBranches: 기본값(false)에서 템플릿은 각 repo의 기본 브랜치에 대해서만 평가돼요. true이면 모든 리포지토리의 모든 브랜치가 필터로 전달돼요. 이 플래그를 사용한다면 branchMatch 필터를 사용하고 싶을 거예요.
  • tokenRef: 요청에 사용할 Gitea 접근 토큰을 담고 있는 Secret 이름과 키. 지정하지 않으면 익명 요청을 하며, 이는 더 낮은 rate limit을 갖고 공개 리포지토리만 볼 수 있어요.
  • insecure: 자체 서명 TLS 인증서 허용.
  • excludeArchivedRepos: 보관된 리포지토리를 제외. 기본값 false

이 SCM provider는 아직 라벨 필터링을 지원하지 않아요.

사용 가능한 clone 프로토콜은 sshhttps예요.

Bitbucket Server

Bitbucket Server API(1.0)를 사용해 프로젝트의 repo를 스캔해요. Bitbucket Server는 Bitbucket Cloud(API 2.0)와 다름에 유의하세요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
  - scmProvider:
      bitbucketServer:
        project: myproject
        # URL of the Bitbucket Server. Required.
        api: https://mycompany.bitbucket.org
        # If true, scan every branch of every repository. If false, scan only the default branch. Defaults to false.
        allBranches: true
        # Credentials for Basic authentication (App Password). Either basicAuth or bearerToken
        # authentication is required to access private repositories
        basicAuth:
          # The username to authenticate with
          username: myuser
          # Reference to a Secret containing the password or personal access token.
          passwordRef:
            secretName: mypassword
            key: password
        # Credentials for Bearer Token (App Token) authentication. Either basicAuth or bearerToken
        # authentication is required to access private repositories
        bearerToken:
          # Reference to a Secret containing the bearer token.
          tokenRef:
            secretName: repotoken
            key: token
        # If true, skips validating the SCM provider's TLS certificate - useful for self-signed certificates.
        insecure: true
        # Reference to a ConfigMap containing trusted CA certs - useful for self-signed certificates. (optional)
        caRef:
          configMapName: argocd-tls-certs-cm
          key: bitbucket-ca
        # Support for filtering by labels is TODO. Bitbucket server labels are not supported for PRs, but they are for repos
  template:
  # ...
  • project: Bitbucket 프로젝트의 필수 이름
  • api: Bitbucket REST api에 접근하는 필수 URL.
  • allBranches: 기본값(false)에서 템플릿은 각 repo의 기본 브랜치에 대해서만 평가돼요. true이면 모든 리포지토리의 모든 브랜치가 필터로 전달돼요. 이 플래그를 사용한다면 branchMatch 필터를 사용하고 싶을 거예요.

개인 리포지토리에 접근하려면 Basic auth 자격 증명도 제공해야 해요(현재 지원되는 유일한 인증): * username: 인증에 사용할 사용자 이름. 관련 repo에 대한 읽기 접근만 필요해요. * passwordRef: 요청에 사용할 비밀번호 또는 개인 접근 토큰을 담고 있는 Secret 이름과 키.

Bitbucket App Token의 경우 bearerToken 섹션을 사용하세요. * tokenRef: 요청에 사용할 app token을 담고 있는 Secret 이름과 키.

자체 서명 BitBucket Server 인증서의 경우 다음 옵션이 유용할 수 있어요: * insecure: 기본값(false) - SCM 인증서 유효성 확인 건너뜀 - 자체 서명 TLS 인증서에 유용. * caRef: 신뢰할 BitBucket 서버 인증서를 담고 있는 선택적 ConfigMap 이름과 키 - 자체 서명 TLS 인증서에 유용. 신뢰할 인증서를 보유한 ArgoCD CM을 참조할 수 있음.

사용 가능한 clone 프로토콜은 sshhttps예요.

Azure DevOps

Azure DevOps 조직 내 팀 프로젝트를 기반으로 적격 리포지토리를 조회하는 데 Azure DevOps API를 사용해요. 기본 Azure DevOps URL은 https://dev.azure.com이며, azureDevOps.api 필드로 오버라이드할 수 있어요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
  - scmProvider:
      azureDevOps:
        # The Azure DevOps organization.
        organization: myorg
        # URL to Azure DevOps. Optional. Defaults to https://dev.azure.com.
        api: https://dev.azure.com
        # If true, scan every branch of eligible repositories. If false, check only the default branch of the eligible repositories. Defaults to false.
        allBranches: true
        # The team project within the specified Azure DevOps organization.
        teamProject: myProject
        # Reference to a Secret containing the Azure DevOps Personal Access Token (PAT) used for accessing Azure DevOps.
        accessTokenRef:
          secretName: azure-devops-scm
          key: accesstoken
  template:
  # ...
  • organization: 필수. Azure DevOps 조직 이름.
  • teamProject: 필수. 지정된 organization 내 팀 프로젝트 이름.
  • accessTokenRef: 필수. 요청에 사용할 Azure DevOps Personal Access Token(PAT)을 담고 있는 Secret 이름과 키.
  • api: 선택 사항. Azure DevOps URL. 설정하지 않으면 https://dev.azure.com 사용.
  • allBranches: 선택 사항, 기본 false. true이면 적격 리포지토리의 모든 브랜치를 스캔. false이면 적격 리포지토리의 기본 브랜치만 확인.

Bitbucket Cloud

Bitbucket 모드는 Bitbucket API V2를 사용해 bitbucket.org의 워크스페이스를 스캔해요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
  - scmProvider:
      bitbucket:
        # The workspace id (slug).
        owner: "example-owner"
        # The user to use for basic authentication with an app password.
        user: "example-user"
        # If true, scan every branch of every repository. If false, scan only the main branch. Defaults to false.
        allBranches: true
        # Reference to a Secret containing an app password.
        appPasswordRef:
          secretName: appPassword
          key: password
  template:
  # ...
  • owner: 리포지토리를 조회할 때 사용할 워크스페이스 ID(slug).
  • user: bitbucket.org의 Bitbucket API V2에 인증하는 데 사용할 사용자.
  • allBranches: 기본값(false)에서 템플릿은 각 repo의 main 브랜치에 대해서만 평가돼요. true이면 모든 리포지토리의 모든 브랜치가 필터로 전달돼요. 이 플래그를 사용한다면 branchMatch 필터를 사용하고 싶을 거예요.
  • appPasswordRef: 요청에 사용할 bitbucket app password를 담고 있는 Secret 이름과 키.

이 SCM provider는 아직 라벨 필터링을 지원하지 않아요.

사용 가능한 clone 프로토콜은 sshhttps예요.

AWS CodeCommit (Alpha)

AWS ResourceGroupsTagging과 AWS CodeCommit API를 사용해 AWS 계정과 리전에 걸친 repo를 스캔해요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
    - scmProvider:
        awsCodeCommit:
          # AWS region to scan repos.
          # default to the environmental region from ApplicationSet controller.
          region: us-east-1
          # AWS role to assume to scan repos.
          # default to the environmental role from ApplicationSet controller.
          role: arn:aws:iam::111111111111:role/argocd-application-set-discovery
          # If true, scan every branch of every repository. If false, scan only the main branch. Defaults to false.
          allBranches: true
          # AWS resource tags to filter repos with.
          # see https://docs.aws.amazon.com/resourcegroupstagging/latest/APIReference/API_GetResources.html#resourcegrouptagging-GetResources-request-TagFilters for details
          # default to no tagFilters, to include all repos in the region.
          tagFilters:
            - key: organization
              value: platform-engineering
            - key: argo-ready
  template:
  # ...
  • region: (선택) repo를 스캔할 AWS 리전. 기본적으로 ApplicationSet 컨트롤러의 현재 리전 사용.
  • role: (선택) repo를 스캔하기 위해 assume할 AWS 역할. 기본적으로 ApplicationSet 컨트롤러의 현재 역할 사용.
  • allBranches: (선택) true이면 적격 리포지토리의 모든 브랜치를 스캔. false이면 적격 리포지토리의 기본 브랜치만 확인. 기본 false.
  • tagFilters: (선택) AWS CodeCommit repo를 필터링할 tagFilter 목록. 자세한 내용은 AWS ResourceGroupsTagging API 참고. 기본적으로 필터 없음.

이 SCM provider는 다음 기능을 지원하지 않아요:

  • 라벨 필터링
  • sha, short_shashort_sha_7 템플릿 파라미터

사용 가능한 clone 프로토콜은 ssh, httpshttps-fips예요.

AWS IAM 권한 고려사항 (AWS IAM Permission Considerations)

AWS CodeCommit repo를 발견하기 위해 AWS API를 호출하려면 ApplicationSet 컨트롤러가 현재 AWS 리전, AWS 자격 증명 같은 유효한 환경 AWS 구성으로 구성되어야 해요. AWS 구성은 Instance Metadata Service(IMDS), 구성 파일, 환경 변수, 또는 IAM roles for service accounts(IRSA) 같은 모든 표준 옵션으로 제공할 수 있어요.

awsCodeCommit 속성에 role이 제공되는지 여부에 따라 AWS IAM 권한 요구사항이 달라져요.

ApplicationSet 컨트롤러와 같은 AWS 계정의 AWS CodeCommit 리포지토리 발견

role을 지정하지 않으면 ApplicationSet 컨트롤러는 자체 AWS 신원을 사용해 AWS CodeCommit repo를 스캔해요. 모든 AWS CodeCommit repo가 Argo CD와 같은 AWS 계정에 있는 간단한 설정에 적합해요.

ApplicationSet 컨트롤러 AWS 신원이 repo 발견에 직접 사용되므로 아래 AWS 권한이 부여되어야 해요:

  • tag:GetResources
  • codecommit:ListRepositories
  • codecommit:GetRepository
  • codecommit:GetFolder
  • codecommit:ListBranches

AWS 계정과 리전에 걸친 AWS CodeCommit 리포지토리 발견

role을 지정하면 ApplicationSet 컨트롤러는 먼저 role을 assume하고 repo 발견에 사용해요. 이를 통해 서로 다른 AWS 계정과 리전에서 repo를 발견하는 더 복잡한 사용 사례가 가능해져요.

ApplicationSet 컨트롤러 AWS 신 identity에는 대상 AWS 역할을 assume할 권한이 부여되어야 해요:

  • sts:AssumeRole

모든 AWS 역할은 repo 발견 관련 권한을 가져야 해요:

  • tag:GetResources
  • codecommit:ListRepositories
  • codecommit:GetRepository
  • codecommit:GetFolder
  • codecommit:ListBranches

필터 (Filters)

필터는 어떤 리포지토리를 생성 대상으로 선택할지 선택할 수 있게 해줘요. 각 필터는 하나 이상의 조건을 선언할 수 있으며, 모두 통과해야 해요. 여러 필터가 있으면 그중 하나라도 매치되면 리포지토리가 포함돼요. 필터가 지정되지 않으면 모든 리포지토리가 처리돼요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
  - scmProvider:
      filters:
      # Include any repository starting with "myapp" AND including a Kustomize config AND labeled with "deploy-ok" ...
      - repositoryMatch: ^myapp
        pathsExist: [kubernetes/kustomization.yaml]
        labelMatch: deploy-ok
      # ... OR include any repository starting with "otherapp" AND a Helm folder and doesn't have file disabledrepo.txt.
      - repositoryMatch: ^otherapp
        pathsExist: [helm]
        pathsDoNotExist: [disabledrepo.txt]
  template:
  # ...
  • repositoryMatch: 리포지토리 이름과 매칭되는 regexp.
  • pathsExist: 리포지토리 내 존재해야 하는 경로 배열. 파일 또는 디렉토리일 수 있음.
  • pathsDoNotExist: 리포지토리 내 존재하지 않아야 하는 경로 배열. 파일 또는 디렉토리일 수 있음.
  • labelMatch: 리포지토리 라벨과 매칭되는 regexp. 어떤 라벨이라도 일치하면 리포지토리가 포함돼요.
  • branchMatch: 브랜치 이름과 매칭되는 regexp.

템플릿 (Template)

다른 모든 generator와 마찬가지로 ApplicationSet 리소스 템플릿 안에서 사용할 여러 파라미터가 생성돼요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  goTemplate: true
  goTemplateOptions: ["missingkey=error"]
  generators:
  - scmProvider:
    # ...
  template:
    metadata:
      name: '{{ .repository }}'
    spec:
      source:
        repoURL: '{{ .url }}'
        targetRevision: '{{ .branch }}'
        path: kubernetes/
      project: default
      destination:
        server: https://kubernetes.default.svc
        namespace: default
  • organization: 리포지토리가 속한 조직의 이름.
  • repository: 리포지토리의 이름.
  • repository_id: 리포지토리의 id.
  • url: 리포지토리의 clone URL.
  • branch: 리포지토리의 기본 브랜치.
  • sha: 브랜치의 Git commit SHA.
  • short_sha: 브랜치의 축약 Git commit SHA(8자 또는 더 짧으면 sha의 길이).
  • short_sha_7: 브랜치의 축약 Git commit SHA(7자 또는 더 짧으면 sha의 길이).
  • labels: Gitea의 경우 쉼표로 구분된 리포지토리 라벨 목록, Gitlab과 Github의 경우 리포지토리 토픽. Bitbucket Cloud, Bitbucket Server, Azure DevOps에서는 지원되지 않음.
  • branchNormalized: 소문자 영숫자, - 또는 .만 포함하도록 정규화된 branch 값.

values 필드로 추가 key-value 쌍 전달 (Pass additional key-value pairs via values field)

어떤 SCM generator든 values 필드로 추가적이고 임의의 문자열 key-value 쌍을 전달할 수 있어요. values 필드로 추가된 값은 values.(field)로 추가돼요.

이 예시에서 name 파라미터 값이 전달돼요. organizationrepository에서 보간되어 다른 템플릿 이름을 생성해요.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  goTemplate: true
  goTemplateOptions: ["missingkey=error"]
  generators:
  - scmProvider:
      bitbucketServer:
        project: myproject
        api: https://mycompany.bitbucket.org
        allBranches: true
        basicAuth:
          username: myuser
          passwordRef:
            secretName: mypassword
            key: password
      values:
        name: "{{.organization}}-{{.repository}}"

  template:
    metadata:
      name: '{{ .values.name }}'
    spec:
      source:
        repoURL: '{{ .url }}'
        targetRevision: '{{ .branch }}'
        path: kubernetes/
      project: default
      destination:
        server: https://kubernetes.default.svc
        namespace: default

[!NOTE] values. 프리픽스는 항상 generators.scmProvider.values 필드를 통해 제공된 값 앞에 붙어요. template의 파라미터 이름에 이 프리픽스를 포함해야 해요.

values에서는 위에서 언급한 SCM generator가 설정한 모든 필드도 보간할 수 있어요.

더 알아보기 (Learn more)