본문 바로가기
Deployment/GitHub

Azure OIDC 로그인 설정과 VS Code Marketplace 자동화 게시

by curious week 2026. 10. 14.

GitHub Actions YAML 작성 - Azure OIDC 로그인 설정 - VS Code Marketplace 자동화 게시까지

1. Github actons YAML 작성 (위치: .github/workflows/marketplace.yml)

선택한 게시 브랜치의 소스를 패키징해 단일 VSIX로 게시할 때, 

name: VS Code Marketplace

on:
  workflow_dispatch:
    inputs:
      operation:
        description: "identity: ID 조회 / verify: 권한 확인 / publish: 실제 게시"
        required: true
        default: verify
        type: choice
        options:
          - identity
          - verify
          - publish

permissions:
  contents: read
  id-token: write

# 같은 저장소에서 게시 작업이 동시에 실행되지 않게 합니다.
concurrency:
  group: vscode-marketplace-${{ github.repository }}
  cancel-in-progress: false

env:
  # [교체: 게시 브랜치] 예: main
  PUBLISH_BRANCH: "[교체: 게시 브랜치]"

  # [교체: 확장 디렉터리] 예: apps/vscode-extension 또는 .
  EXTENSION_DIR: "[교체: 확장 디렉터리]"

  # [교체: Marketplace publisher ID] 예: frillab
  MARKETPLACE_PUBLISHER: "[교체: Marketplace publisher ID]"

  NODE_VERSION: "22"

jobs:
  marketplace:
    runs-on: ubuntu-latest
    timeout-minutes: 20

    steps:
      - name: Validate execution branch
        env:
          WORKFLOW_REF: ${{ github.ref }}
        shell: bash
        run: |
          set -euo pipefail

          expected_ref="refs/heads/${PUBLISH_BRANCH}"

          if [[ "$WORKFLOW_REF" != "$expected_ref" ]]; then
            echo "::error::Run this workflow from ${PUBLISH_BRANCH}."
            exit 1
          fi

      - name: Check out source
        if: inputs.operation != 'identity'
        uses: actions/checkout@v7

      - name: Set up Node.js
        if: inputs.operation != 'identity'
        uses: actions/setup-node@v7
        with:
          node-version: ${{ env.NODE_VERSION }}

      - name: Install extension dependencies
        if: inputs.operation != 'identity'
        working-directory: ${{ env.EXTENSION_DIR }}
        run: npm ci

      - name: Validate extension publisher
        if: inputs.operation != 'identity'
        working-directory: ${{ env.EXTENSION_DIR }}
        shell: bash
        run: |
          set -euo pipefail

          node <<'NODE'
          const manifest = require("./package.json");
          const expected = process.env.MARKETPLACE_PUBLISHER;

          if (manifest.publisher !== expected) {
            console.error(
              `Publisher mismatch: package.json=${manifest.publisher}, expected=${expected}`
            );
            process.exit(1);
          }

          console.log(
            `Extension: ${manifest.publisher}.${manifest.name}@${manifest.version}`
          );
          NODE

      - name: Sign in to Azure using GitHub OIDC
        uses: azure/login@v3
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: Get Marketplace identity ID
        if: inputs.operation == 'identity'
        shell: bash
        run: |
          set -euo pipefail

          az rest \
            --method GET \
            --url https://app.vssps.visualstudio.com/_apis/profile/profiles/me \
            --resource 499b84ac-1321-427f-aa17-267ca6975798 \
            --query id \
            --output tsv

      - name: Verify Marketplace publisher access
        if: inputs.operation != 'identity'
        working-directory: ${{ env.EXTENSION_DIR }}
        env:
          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
        run: |
          npx --no-install vsce verify-pat \
            "$MARKETPLACE_PUBLISHER" \
            --azure-credential

      - name: Package extension
        if: inputs.operation == 'publish'
        working-directory: ${{ env.EXTENSION_DIR }}
        run: |
          npx --no-install vsce package \
            --out marketplace-extension.vsix

      - name: Publish extension
        if: inputs.operation == 'publish'
        working-directory: ${{ env.EXTENSION_DIR }}
        env:
          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
        run: |
          npx --no-install vsce publish \
            --azure-credential \
            --packagePath marketplace-extension.vsix

2. 확장 프로젝트 준비 확인 (@vscode/vsce를 개발 의존성이 있어야 합니다.)

확장 프로그램 디렉토리에서 실행!

npm install --save-dev @vscode/vsce

package.json의 publisher ID도 맞춰야합니다.

# package.json

{
  "publisher": "[교체: Marketplace publisher ID]"
}

3. Azure Portal 등록

 

Microsoft Azure

 

portal.azure.com

1) Azure Portal 로그인 (https://portal.azure.com/)

2) 관리 ID (Managed Identities) -> 만들기 (Create)

  • Subscription (구독): 사용할 Azure 구독
  • Resource group (리소스 그룹): 새로 만들기 -> "[교체!: 프로젝트 명]-publishing"
  • Name: [교체!: 프로젝트 명]-marketplace
  • Region (지역): 선택 가능한 지역

Review + create (검토 + 만들기) 클릭 -> Create (만들기) 클릭

3) ID 기록 해두기 (클라이언트 ID, 구독 ID, 테넌트 ID)

 

생성한 관리 ID의 Overview / 개요에서 배포 정보 -> 리소스 선택

  • Client ID (클라이언트 ID)
  • Subscription ID (구독 ID)
  • Tenant ID (테넌트 ID): 없을 경우 Microsoft Entra ID -> Overview -> Tenant ID

4) Azure Reader (독자) 권한 부여

Access control (IAM) (엑세스 제어 (IAM)) -> Add (추가) → Add role assignment (역할 할당 추가)

독자 == Reader

 

  • Role (역할): Reader (독자)
  • Assign access to (다음에 대한 엑세스 할당): Managed identity (관리 ID)
  • Select members (+ 구성원 선택): 방금 만든 [교체! 프로젝트 명]-marketplace
  • 하단 Review + assign (검토 + 할당) 클릭

5) Github와 관리 ID 연결

Settings (설정) -> Federated credentials (페더레이션된 자격 증명) -> Add credential (자격 증명 추가)

https://api.github.com/orgs/FrilLab

  {
    "id": 아이디!!,
    "node_id": "노드아이디",
    "name": "저장소 이름",
    "full_name": "조직 이름/저장소 이름",
    ...
    ...
 }
  • Entity type (엔티티): Branch (분기)
  • Branch (분기): main
  • Subject identifier (주체 식별자, 같은 형식인지 확인!): repo:[교체! 조직 이름]/[교체! 프로젝트 명]:ref:refs/heads/main
    • 🆗: repo:test/test:ref:refs/heads/main
    • ❌: repo:test@조직ID/test@프로젝트ID:ref:refs/heads/main
  • Credential name: github-[교체! 프로젝트 명]-main
  • Audience (대상 그룹): api://AzureADTokenExchange
  • Add (추가) 클릭

4. Github secrets 등록 (3-3에서 기록해 둔 Tenant ID, Client ID, Subscription ID 등록)

해당 Repo -> Settings -> Secrets and Variables -> Actions -> New repository secret

  • AZURE_CLIENT_ID: 관리 ID의 Client ID
  • AZURE_TENANT_ID: 해당 Azure 디렉터리의 Tenant ID
  • AZURE_SUBSCRIPTION_ID: 관리 ID가 속한 Subscription ID

Client Secret이나 VSCE_PAT을 새로 만들 필요는 없습니다.

5. Marketplace 등록용 ID 조회 (위치: github/workflows/marketplace-identity-check.yml)

1) 준비 사항 / 유의 사항

  • GitHub secrets의 AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID
  • 해당 관리 ID에 등록한 연합 자격 증명의 Subject (Azure의 Subject는 저장소마다 맞춰야 합니다.)
repo:[교체: 소유자]/[교체: 저장소]:ref:refs/heads/[교체: 브랜치]
  • 실행 브랜치가 main이 아니라면 브랜치 검사와 오류 문구 수정

2) marketplace-identity-check.yml 작성

marketplace-identity-check.yml 작성 후 -> main 병합 -> workflow 실행

name: Check Marketplace Identity

on:
  workflow_dispatch:

permissions:
  contents: read
  id-token: write

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - name: Require main
        env:
          WORKFLOW_REF: ${{ github.ref }}
        run: |
          if [ "$WORKFLOW_REF" != "refs/heads/main" ]; then
            echo "::error::Run this workflow from main."
            exit 1
          fi

      - name: Sign in to Azure
        uses: azure/login@v3
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: Get Marketplace identity ID
        run: |
          az rest \
            --method GET \
            --url https://app.vssps.visualstudio.com/_apis/profile/profiles/me \
            --resource 499b84ac-1321-427f-aa17-267ca6975798 \
            --query id \
            --output tsv

3) Actions에서 Marketplace identity ID 얻기

숫자로 시작하는 Marketplace identity ID만 저장

6. publisher(package.json에 적은 publisher)에 구성원 추가

 

 

Visual Studio Marketplace

Extensions for Visual Studio family of products on Visual Studio Marketplace

marketplace.visualstudio.com

1) Visual Studio Marketplace (https://marketplace.visualstudio.com/)

더보기

2) + Create Publisher

Package.json에 적은 Publisher 이름과 동일해야함.

3) + New extension (VISX 파일을 드래그 엔 드롭)

4) Members (구성원 관리) -> 추가 (Add) -> User name: Marketplace identity ID (Role: Contributeor) -> 저장

User name은 5-3의 Marketplace identity  ID

7. 권한 확인 후 게시 (1번에 작성한 워크플로우를 실행 실패할 경우 Actions 확인)

'Deployment > GitHub' 카테고리의 다른 글

실제로 사용하는 Git 명령어  (0) 2026.05.25
Github Actions  (1) 2026.05.05
Learn Git Branching (2) remote  (0) 2026.05.01
GitHub Skills  (0) 2026.04.30
Learn Git Branching (1) main  (0) 2026.04.30