Skip to content

feat(workflows): add reusable marketplace-publish workflow#10

Merged
k2kite-megankim merged 1 commit into
mainfrom
feat/marketplace-publish-reusable
May 3, 2026
Merged

feat(workflows): add reusable marketplace-publish workflow#10
k2kite-megankim merged 1 commit into
mainfrom
feat/marketplace-publish-reusable

Conversation

@k2kite-megankim
Copy link
Copy Markdown
Contributor

요약

LVIS 플러그인 마켓플레이스 publish 파이프라인의 단일 SoT. 현재 7개 레포 (template + 6 플러그인) 가 ~330줄짜리 `publish.yml` 을 각자 들고 있는 N=7 중복 → 1곳 단일 소스로 전환. 호출자는 ~12줄 thin caller 만 유지.

동기

`lvis-plugin-local-indexer` 의 두 차례 회귀 (worker dir drop on v0.1.20, lockfile drop on v0.1.21) 가 모두 "workflow 와 `package.json:files[]` 동시 갱신 누락" 패턴이었음. PR #31 + 6 plugin sweep 으로 SoT 패턴은 정렬됐지만, 다음 publish 파이프라인 변경 (보안 강화 / API 스키마 마이그레이션) 은 또 sweep 6번 필요. 이번 PR 이 그 sweep 자체를 1번으로 압축.

API

Inputs

  • `slug` (string, required) — catalog id. `plugin.json.id` 와 cross-check 됨 (drift = 즉시 fail-loud).

Secrets

동작

본문은 lvis-plugin-template post-PR-31 의 publish.yml 을 그대로 lift:

  • `package.json:files[]` SoT 기반 artifact 구성
  • GHA expression-injection sink 차단 (`zip -@` stdin)
  • Segment-aware path traversal 검증, boundary-anchored sensitive-file regex
  • realpath every entry against repo root
  • `--symlinks` zip flag (외부 symlink 차단)
  • SemVer 검증, ancestor check, catalog 409 sha 비교 모두 보존

Caller 패턴

```yaml
on:
push:
tags: ['v*..']
jobs:
publish:
uses: lvis-project/.github/.github/workflows/marketplace-publish.yml@v1
with:
slug: meeting
secrets:
MARKETPLACE_API_KEY: ${{ secrets.MARKETPLACE_API_KEY }}
MARKETPLACE_BASE_URL: ${{ secrets.MARKETPLACE_BASE_URL }}
```

도입 plan

  1. 이 PR 머지 + `v1` tag (.github repo)
  2. Canary: lvis-plugin-pageindex (가장 복잡 — Python lockfile + worker 번들) 을 caller 로 변환, patch bump + tag → reusable workflow 실증
  3. 그린이면 나머지 5 플러그인 + lvis-plugin-template sweep

Test plan

  • yaml 문법 검증
  • 머지 후 v1 tag → pageindex canary PR 에서 실제 publish 동작 확인
  • 6 플러그인 + template caller PR 작성

References lvis-plugin-template#30, lvis-plugin-template#31 (sweep 의 P2 단계)

🤖 Generated with Claude Code

Single source of truth for the LVIS plugin marketplace publish
pipeline. Replaces N=7 copies of `publish.yml` (lvis-plugin-template +
6 plugin repos) that drifted across repos and led to two consecutive
regressions on lvis-plugin-local-indexer (worker dir drop on v0.1.20,
python-requirements.lock drop on v0.1.21). Future changes — new
security guards, marketplace API contract migrations, zip layout
adjustments — land here once and propagate via the
`uses: lvis-project/.github/.github/workflows/marketplace-publish.yml@vN`
caller reference.

Inputs:
- `slug` (string, required): catalog id, must equal `plugin.json.id`.
  Cross-checked at runtime so a drift between the caller's `with: slug:`
  and the manifest fails fast (silent corruption guard).

Secrets:
- `MARKETPLACE_API_KEY` (required): bearer for POST /versions.
- `MARKETPLACE_BASE_URL` (optional): defaults to
  https://marketplace.lvisai.xyz when unset.

The pipeline body is lifted verbatim from lvis-plugin-template's
publish.yml as of post-PR-31 (the `package.json:files[]` SoT pattern
+ all defense-in-depth guards: GHA expression-injection sink closure
via `zip -@`, segment-aware traversal check, boundary-anchored
sensitive-file regex, realpath-on-every-entry, `--symlinks` zip flag).

Caller pattern — each plugin's publish.yml becomes ~12 lines:

```yaml
on:
  push:
    tags: ['v*.*.*']
jobs:
  publish:
    uses: lvis-project/.github/.github/workflows/marketplace-publish.yml@v1
    with:
      slug: meeting
    secrets:
      MARKETPLACE_API_KEY: ${{ secrets.MARKETPLACE_API_KEY }}
      MARKETPLACE_BASE_URL: ${{ secrets.MARKETPLACE_BASE_URL }}
```

Adoption plan:
1. Land this PR + tag the .github repo `v1`.
2. Canary: convert lvis-plugin-pageindex (most complex — Python
   lockfile + worker bundle) to a caller pointing at `@v1`. Bump
   patch + tag → real publish through reusable.
3. If green, sweep the other 5 plugins + lvis-plugin-template
   (template gets its own caller so future template forks inherit
   the thin shape).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant