- src/dist 산출물 분리 원칙 정리(.gitignore, .gitattributes) - 루트 및 주요 폴더(config/scripts/prompts/tests/src, 런타임 폴더 5종)에 안내용 README.md 추가 - CHANGELOG.md, LICENSE, docs/ops/05-release-and-versioning.md 추가 - docs/README.md 문서 지도 갱신
149 lines
6.4 KiB
PowerShell
149 lines
6.4 KiB
PowerShell
#Requires -Version 5.1
|
|
<#
|
|
.SYNOPSIS
|
|
agy.exe 존재를 확인하고, 없으면 공식 install.ps1 로 무인 설치한다.
|
|
|
|
.DESCRIPTION
|
|
1순위: 공식 설치 스크립트 https://antigravity.google/cli/install.ps1
|
|
(SHA512 무결성 검증 내장, 이미 설치돼 있으면 아무 것도 하지 않고
|
|
종료 코드 0 으로 빠지는 멱등한 스크립트 — agy CLI SSOT §3.3 실측).
|
|
2순위: winget (1순위가 실패했을 때만 시도).
|
|
|
|
설치 여부와 별개로 "인증(로그인) 여부"도 가볍게 점검한다. agy 는 OAuth
|
|
토큰을 사용자 프로필 아래 평문 파일로 저장한다(agy CLI SSOT §4.2 실측:
|
|
~\.gemini\antigravity-cli\antigravity-oauth-token). 그 파일의 존재만
|
|
확인하고, 실제로 토큰이 유효한지 확인하는 헤드리스 왕복 호출은 하지
|
|
않는다 — 그 호출 자체가 수만 토큰 비용을 태우므로(SSOT §4.3 경고),
|
|
설치 스크립트 안에서 매번 돌릴 일이 아니다. 진짜 유효성 판정은 실제
|
|
작업 호출의 성공/실패로 한다(agy/client.py 의 책임).
|
|
|
|
.PARAMETER Force
|
|
이미 정상 설치되어 있어도 재설치를 시도한다.
|
|
|
|
.OUTPUTS
|
|
표준 출력에 사람이 읽을 진행 메시지, 마지막 줄에 "VERSION=<버전>"
|
|
(설치가 확인됐을 때만) — GUI/CLI 가 파싱하고 싶으면 이 줄만 보면 된다.
|
|
|
|
.EXITCODE
|
|
0 : 정상 — agy.exe 설치 확인 + 인증 토큰 파일 존재.
|
|
10 : 설치 필요 — agy.exe 를 (재)설치하지 못했다.
|
|
11 : 인증 필요 — agy.exe 는 설치돼 있지만 로그인 토큰 파일이 없다.
|
|
`agy login` 을 사용자가 직접 수행해야 한다(대화형 브라우저 로그인이라
|
|
무인화할 수 없다 — agy CLI SSOT §4.1).
|
|
|
|
.EXAMPLE
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\bootstrap_agy.ps1
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[switch]$Force
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Continue'
|
|
|
|
function Write-Step { param([string]$Message) Write-Host "[bootstrap_agy] $Message" }
|
|
function Write-Warn { param([string]$Message) Write-Host "[bootstrap_agy] ! $Message" -ForegroundColor Yellow }
|
|
function Write-Good { param([string]$Message) Write-Host "[bootstrap_agy] + $Message" -ForegroundColor Green }
|
|
|
|
# 설치·점검 도중 백그라운드 self-update 가 끼어들면 바이너리가 교체돼
|
|
# 검증이 흔들린다. 이 프로세스 범위에서만 끈다(agy CLI SSOT §3.6).
|
|
$env:AGY_CLI_DISABLE_AUTO_UPDATE = 'true'
|
|
|
|
# 절대경로 고정 — where.exe 는 winget Links 심볼릭까지 잡아 두 경로가
|
|
# 나올 수 있으므로(agy CLI SSOT §3.2 실측) 신뢰하지 않는다.
|
|
$agyExe = Join-Path $env:LOCALAPPDATA 'agy\bin\agy.exe'
|
|
$agyToken = Join-Path $env:USERPROFILE '.gemini\antigravity-cli\antigravity-oauth-token'
|
|
|
|
function Test-AgyOk {
|
|
<#
|
|
agy.exe 가 존재하고 실제로 실행되는지 확인한다.
|
|
0바이트 스텁·중단된 다운로드를 걸러낸다(실측 정상 크기 약 187MB).
|
|
성공하면 버전 문자열을, 실패하면 $null 을 돌려준다.
|
|
#>
|
|
if (-not (Test-Path -LiteralPath $agyExe)) { return $null }
|
|
$item = Get-Item -LiteralPath $agyExe -ErrorAction SilentlyContinue
|
|
if (-not $item -or $item.Length -lt 1MB) { return $null }
|
|
try {
|
|
$v = & $agyExe --version 2>$null
|
|
} catch {
|
|
return $null
|
|
}
|
|
if ($LASTEXITCODE -ne 0 -or -not $v) { return $null }
|
|
return ($v | Select-Object -First 1).ToString().Trim()
|
|
}
|
|
|
|
function Test-AgyAuthenticated {
|
|
<#
|
|
인증 여부의 가벼운(비용 없는) 근사치: 토큰 파일 존재 여부.
|
|
실제 유효성(만료 여부)까지는 확인하지 않는다 — §4.3 경고 참조.
|
|
#>
|
|
return (Test-Path -LiteralPath $agyToken)
|
|
}
|
|
|
|
Write-Step "확인 경로: $agyExe"
|
|
|
|
$version = Test-AgyOk
|
|
if ($version -and -not $Force) {
|
|
Write-Good "이미 설치되어 있습니다. (버전 $version)"
|
|
} else {
|
|
if ($Force) {
|
|
Write-Step '재설치를 요청받았습니다. 설치를 진행합니다.'
|
|
} else {
|
|
Write-Step '설치되어 있지 않거나 손상된 것으로 보입니다. 설치를 진행합니다.'
|
|
}
|
|
|
|
# ------------------------------------------------------------ 1순위: 공식 설치 스크립트
|
|
Write-Step '공식 설치 스크립트를 받는 중... (irm https://antigravity.google/cli/install.ps1 | iex)'
|
|
try {
|
|
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
|
|
} catch {
|
|
Write-Warn 'TLS 1.2 강제 설정에 실패했습니다. 기본 프로토콜로 계속합니다.'
|
|
}
|
|
try {
|
|
Invoke-Expression (Invoke-RestMethod -Uri 'https://antigravity.google/cli/install.ps1' -UseBasicParsing)
|
|
} catch {
|
|
Write-Warn "공식 설치 스크립트 실행 실패: $($_.Exception.Message)"
|
|
}
|
|
|
|
$version = Test-AgyOk
|
|
if ($version) {
|
|
Write-Good "설치 확인: 버전 $version"
|
|
} else {
|
|
# -------------------------------------------------------- 2순위: winget
|
|
Write-Step '1순위 설치가 확인되지 않았습니다. winget 으로 다시 시도합니다...'
|
|
$winget = Get-Command winget.exe -ErrorAction SilentlyContinue
|
|
if ($winget) {
|
|
try {
|
|
& $winget.Source install --id Google.AntigravityCLI --silent `
|
|
--accept-package-agreements --accept-source-agreements | Out-Null
|
|
} catch {
|
|
Write-Warn "winget 설치 실패: $($_.Exception.Message)"
|
|
}
|
|
} else {
|
|
Write-Warn 'winget 을 사용할 수 없습니다.'
|
|
}
|
|
$version = Test-AgyOk
|
|
if ($version) {
|
|
Write-Good "설치 확인: 버전 $version"
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-not $version) {
|
|
Write-Warn '설치에 실패했습니다. 네트워크 연결 또는 방화벽 설정을 확인해 주세요.'
|
|
Write-Warn " 수동 설치: irm https://antigravity.google/cli/install.ps1 | iex"
|
|
exit 10
|
|
}
|
|
|
|
Write-Host "VERSION=$version"
|
|
|
|
if (-not (Test-AgyAuthenticated)) {
|
|
Write-Warn '로그인 토큰을 찾을 수 없습니다. 로그인이 필요합니다.'
|
|
Write-Warn " 다음 명령을 배치를 돌릴 그 계정으로 실행하세요:"
|
|
Write-Warn " & `"$agyExe`" login"
|
|
exit 11
|
|
}
|
|
|
|
Write-Good '설치와 로그인 토큰 확인이 모두 끝났습니다.'
|
|
exit 0
|