들어가며
“이제와서 시작하는 GitHub 마스터하기” 시리즈의 열일곱 번째 시간입니다. 이번에는 GitHub Packages를 활용하여 다양한 패키지를 호스팅하고 관리하는 방법을 알아보겠습니다. GitHub Packages는 소스 코드와 패키지를 한 곳에서 관리할 수 있게 해주는 통합 패키지 레지스트리입니다.
1. GitHub Packages 개요
지원하는 패키지 유형
1
2
3
4
5
6
7
8
9
10
11
12
13
| Container images:
- Docker
- OCI (Open Container Initiative)
Language packages:
- npm (JavaScript/TypeScript)
- RubyGems (Ruby)
- Maven/Gradle (Java/Kotlin)
- NuGet (.NET)
- Cargo (Rust)
General packages:
- Generic packages (any file type)
|
주요 특징
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 통합성:
- GitHub 저장소와 직접 연결
- Actions와 완벽한 통합
- 권한 관리 일원화
보안:
- 프라이빗 패키지 지원
- 세분화된 접근 제어
- 취약점 스캔 통합
제한사항:
Public repositories:
- 무료 무제한
Private repositories:
- Free: 500MB 저장소, 1GB/월 전송
- Pro: 2GB 저장소, 10GB/월 전송
- Team: 2GB 저장소, 10GB/월 전송
- Enterprise: 50GB 저장소, 100GB/월 전송
|
2. npm 패키지 배포
패키지 설정
package.json:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| {
"name": "@username/my-awesome-package",
"version": "1.0.0",
"description": "An awesome package hosted on GitHub Packages",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist",
"README.md",
"LICENSE"
],
"scripts": {
"build": "tsc",
"prepare": "npm run build",
"test": "jest",
"prepublishOnly": "npm test && npm run build"
},
"repository": {
"type": "git",
"url": "https://github.com/username/my-awesome-package.git"
},
"publishConfig": {
"registry": "https://npm.pkg.github.com"
},
"keywords": ["awesome", "package"],
"author": "Your Name",
"license": "MIT",
"bugs": {
"url": "https://github.com/username/my-awesome-package/issues"
},
"homepage": "https://github.com/username/my-awesome-package#readme"
}
|
npm 설정
.npmrc:
1
2
| @username:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}
|
GitHub Actions로 자동 배포
.github/workflows/npm-publish.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
| name: Publish npm Package
on:
release:
types: [created]
workflow_dispatch:
inputs:
version:
description: 'Version to publish'
required: true
default: 'patch'
type: choice
options:
- patch
- minor
- major
permissions:
contents: read
packages: write
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js $
uses: actions/setup-node@v4
with:
node-version: $
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Lint
run: npm run lint
- name: Type check
run: npm run type-check
publish:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: $
- uses: actions/setup-node@v4
with:
node-version: '18.x'
registry-url: 'https://npm.pkg.github.com'
scope: '@username'
- name: Install dependencies
run: npm ci
- name: Configure Git
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
- name: Bump version
if: github.event_name == 'workflow_dispatch'
run: |
npm version $ --no-git-tag-version
VERSION=$(node -p "require('./package.json').version")
git add package.json package-lock.json
git commit -m "chore: bump version to v$VERSION"
git tag "v$VERSION"
git push origin main --tags
- name: Build package
run: npm run build
- name: Publish to GitHub Packages
run: npm publish
env:
NODE_AUTH_TOKEN: $
- name: Publish to npm (optional)
run: |
npm config set //registry.npmjs.org/:_authToken=$NPM_TOKEN
npm config set registry https://registry.npmjs.org
npm publish --access public
env:
NPM_TOKEN: $
if: secrets.NPM_TOKEN != ''
|
패키지 사용하기
1
2
3
4
5
6
7
8
| # .npmrc 설정
echo "@username:registry=https://npm.pkg.github.com" >> .npmrc
# 인증 (Personal Access Token 필요)
npm login --scope=@username --registry=https://npm.pkg.github.com
# 패키지 설치
npm install @username/my-awesome-package
|
3. Docker 이미지 배포
Dockerfile 준비
Dockerfile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| # Multi-stage build
FROM node:18-alpine AS builder
WORKDIR /app
# 의존성 캐시
COPY package*.json ./
RUN npm ci --only=production
# 앱 복사 및 빌드
COPY . .
RUN npm run build
# Production image
FROM node:18-alpine
# 메타데이터
LABEL org.opencontainers.image.source="https://github.com/username/my-app"
LABEL org.opencontainers.image.description="My awesome application"
LABEL org.opencontainers.image.licenses="MIT"
WORKDIR /app
# 프로덕션 의존성만 복사
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
EXPOSE 3000
USER node
CMD ["node", "dist/server.js"]
|
GitHub Actions로 Docker 이미지 배포
.github/workflows/docker-publish.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
| name: Build and Push Docker Image
on:
push:
branches: [ main ]
tags: [ 'v*' ]
pull_request:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: $
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: $
username: $
password: $
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: $/$
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: $
labels: $
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=$
COMMIT_SHA=$
BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: $/$:$
format: spdx-json
output-file: sbom.spdx.json
- name: Sign container image
if: github.event_name != 'pull_request'
env:
COSIGN_PASSWORD: $
run: |
cosign sign --key cosign.key \
$/$@$
|
Docker 이미지 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 로그인
docker login ghcr.io -u USERNAME -p TOKEN
# 이미지 풀
docker pull ghcr.io/username/my-app:latest
# 실행
docker run -p 3000:3000 ghcr.io/username/my-app:latest
# docker-compose.yml
version: '3.8'
services:
app:
image: ghcr.io/username/my-app:latest
ports:
- "3000:3000"
environment:
- NODE_ENV=production
|
4. Maven 패키지 배포
pom.xml 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
| <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.username</groupId>
<artifactId>my-awesome-library</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>My Awesome Library</name>
<description>An awesome Java library</description>
<url>https://github.com/username/my-awesome-library</url>
<licenses>
<license>
<name>MIT License</name>
<url>https://opensource.org/licenses/MIT</url>
</license>
</licenses>
<developers>
<developer>
<name>Your Name</name>
<email>you@example.com</email>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/username/my-awesome-library.git</connection>
<developerConnection>scm:git:ssh://github.com:username/my-awesome-library.git</developerConnection>
<url>https://github.com/username/my-awesome-library</url>
</scm>
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/username/my-awesome-library</url>
</repository>
</distributionManagement>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
|
Maven settings.xml
~/.m2/settings.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<activeProfiles>
<activeProfile>github</activeProfile>
</activeProfiles>
<profiles>
<profile>
<id>github</id>
<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/username/*</url>
</repository>
</repositories>
</profile>
</profiles>
<servers>
<server>
<id>github</id>
<username>USERNAME</username>
<password>${env.GITHUB_TOKEN}</password>
</server>
</servers>
</settings>
|
GitHub Actions로 Maven 패키지 배포
.github/workflows/maven-publish.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| name: Publish Maven Package
on:
release:
types: [created]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
cache: maven
- name: Configure Maven
uses: s4u/maven-settings-action@v2.8.0
with:
servers: |
[{
"id": "github",
"username": "$",
"password": "$"
}]
- name: Build with Maven
run: mvn clean compile
- name: Run tests
run: mvn test
- name: Publish to GitHub Packages
run: mvn deploy
env:
GITHUB_TOKEN: $
|
5. NuGet 패키지 배포
.csproj 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<PackageId>MyAwesomeLibrary</PackageId>
<Version>1.0.0</Version>
<Authors>Your Name</Authors>
<Company>YourCompany</Company>
<PackageDescription>An awesome .NET library</PackageDescription>
<RepositoryUrl>https://github.com/username/my-awesome-library</RepositoryUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/username/my-awesome-library</PackageProjectUrl>
<PackageTags>awesome;library;dotnet</PackageTags>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
</Project>
|
GitHub Actions로 NuGet 패키지 배포
.github/workflows/nuget-publish.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| name: Publish NuGet Package
on:
release:
types: [published]
env:
DOTNET_VERSION: '6.0.x'
jobs:
publish:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: $
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Test
run: dotnet test --no-restore --verbosity normal
- name: Pack
run: dotnet pack --configuration Release --no-build --output ./artifacts
- name: Push to GitHub Packages
run: |
dotnet nuget add source --username $ \
--password $ \
--store-password-in-clear-text \
--name github "https://nuget.pkg.github.com/username/index.json"
dotnet nuget push "./artifacts/*.nupkg" \
--api-key $ \
--source "github" \
--skip-duplicate
|
6. RubyGems 패키지 배포
gemspec 파일
my-awesome-gem.gemspec:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| Gem::Specification.new do |spec|
spec.name = "my-awesome-gem"
spec.version = "1.0.0"
spec.authors = ["Your Name"]
spec.email = ["you@example.com"]
spec.summary = %q{An awesome Ruby gem}
spec.description = %q{A longer description of this awesome Ruby gem}
spec.homepage = "https://github.com/username/my-awesome-gem"
spec.license = "MIT"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.required_ruby_version = ">= 2.6.0"
spec.add_development_dependency "bundler", "~> 2.0"
spec.add_development_dependency "rake", "~> 13.0"
spec.add_development_dependency "rspec", "~> 3.0"
end
|
GitHub Actions로 RubyGems 배포
.github/workflows/gem-publish.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| name: Publish Ruby Gem
on:
push:
tags:
- v*
jobs:
publish:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true
- name: Run tests
run: bundle exec rake spec
- name: Build gem
run: gem build *.gemspec
- name: Push to GitHub Packages
run: |
mkdir -p ~/.gem
echo "---" > ~/.gem/credentials
echo ":github: Bearer $" >> ~/.gem/credentials
chmod 0600 ~/.gem/credentials
gem push --key github \
--host https://rubygems.pkg.github.com/username \
*.gem
|
7. 멀티 패키지 관리
Monorepo 구조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| my-monorepo/
├── packages/
│ ├── core/
│ │ ├── package.json
│ │ └── src/
│ ├── ui/
│ │ ├── package.json
│ │ └── src/
│ └── utils/
│ ├── package.json
│ └── src/
├── docker/
│ ├── app/
│ │ └── Dockerfile
│ └── worker/
│ └── Dockerfile
├── lerna.json
├── package.json
└── .github/
└── workflows/
└── publish-all.yml
|
Lerna를 사용한 멀티 패키지 배포
lerna.json:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| {
"version": "independent",
"npmClient": "npm",
"command": {
"publish": {
"registry": "https://npm.pkg.github.com",
"conventionalCommits": true,
"message": "chore(release): publish",
"createRelease": "github"
},
"version": {
"allowBranch": ["main", "release/*"],
"conventionalCommits": true
}
},
"packages": ["packages/*"]
}
|
.github/workflows/publish-all.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| name: Publish All Packages
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: $
- uses: actions/setup-node@v4
with:
node-version: '18'
registry-url: 'https://npm.pkg.github.com'
- name: Configure Git
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
- name: Install dependencies
run: npm ci
- name: Build all packages
run: npm run build
- name: Run tests
run: npm test
- name: Version and publish
run: |
npm run lerna version -- --yes
npm run lerna publish from-git -- --yes
env:
NODE_AUTH_TOKEN: $
GH_TOKEN: $
|
8. 패키지 버전 관리
Semantic Release 설정
.releaserc.json:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| {
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
[
"@semantic-release/github",
{
"assets": [
{
"path": "dist/**/*.js",
"label": "JavaScript distribution"
},
{
"path": "dist/**/*.d.ts",
"label": "TypeScript definitions"
}
]
}
],
[
"@semantic-release/git",
{
"assets": ["CHANGELOG.md", "package.json", "package-lock.json"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
]
]
}
|
자동 버전 관리 워크플로우
.github/workflows/semantic-release.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| name: Semantic Release
on:
push:
branches: [ main ]
permissions:
contents: write
packages: write
issues: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: '18'
registry-url: 'https://npm.pkg.github.com'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Semantic Release
env:
GITHUB_TOKEN: $
NODE_AUTH_TOKEN: $
run: npx semantic-release
|
9. 패키지 사용 및 관리
패키지 권한 관리
1
2
3
4
5
6
7
8
9
10
| # Repository Settings → Manage Access
Package permissions:
- Read: 패키지 다운로드
- Write: 패키지 업로드/수정
- Admin: 패키지 삭제
Visibility:
- Private: 조직/협업자만
- Internal: 조직 내부
- Public: 모든 사용자
|
패키지 메타데이터
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // package.json 예시
{
"name": "@org/package",
"version": "1.0.0",
"description": "Package description",
"keywords": ["github", "packages"],
"homepage": "https://github.com/org/repo#readme",
"bugs": {
"url": "https://github.com/org/repo/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/org/repo.git"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/username"
}
}
|
패키지 사용 통계
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| // 패키지 다운로드 통계 조회
const { Octokit } = require('@octokit/rest');
async function getPackageStats(owner, packageType, packageName) {
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN
});
try {
// 패키지 정보 조회
const { data: pkg } = await octokit.packages.getPackageForOrganization({
package_type: packageType,
package_name: packageName,
org: owner
});
// 버전 목록 조회
const { data: versions } = await octokit.packages.getAllPackageVersionsForPackageOwnedByOrg({
package_type: packageType,
package_name: packageName,
org: owner
});
return {
name: pkg.name,
type: pkg.package_type,
visibility: pkg.visibility,
created_at: pkg.created_at,
updated_at: pkg.updated_at,
version_count: versions.length,
latest_version: versions[0]?.name,
total_downloads: versions.reduce((sum, v) => sum + (v.metadata?.download_count || 0), 0)
};
} catch (error) {
console.error('Error fetching package stats:', error);
throw error;
}
}
|
10. 모범 사례
패키지 보안
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| # 패키지 스캔 워크플로우
name: Package Security Scan
on:
schedule:
- cron: '0 0 * * 0'
workflow_dispatch:
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Scan npm packages
run: |
npm audit --production
npm outdated
- name: Scan Docker images
uses: aquasecurity/trivy-action@master
with:
image-ref: 'ghcr.io/$:latest'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
|
패키지 문서화
1
2
3
4
5
6
7
8
9
10
11
12
| <!-- README.md -->
# Package Name
[](https://github.com/org/repo/packages)
[](https://github.com/org/repo/pkgs/container/image)
[](LICENSE)
## Installation
### npm
```bash
npm install @org/package
|
Docker
1
| docker pull ghcr.io/org/image:latest
|
Maven
1
2
3
4
5
| <dependency>
<groupId>com.github.org</groupId>
<artifactId>package</artifactId>
<version>1.0.0</version>
</dependency>
|
Usage
[사용 예제]
API Documentation
[API 문서]
Contributing
[기여 가이드]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
### 비용 최적화
```yaml
최적화 전략:
이미지 크기 줄이기:
- Multi-stage builds 사용
- Alpine 기반 이미지 사용
- 불필요한 파일 제외
캐시 활용:
- Layer 캐싱 최적화
- GitHub Actions 캐시 사용
정리 정책:
- 오래된 버전 자동 삭제
- 미사용 패키지 정리
모니터링:
- 사용량 추적
- 비용 알림 설정
|
마무리
GitHub Packages는 코드와 패키지를 한 곳에서 관리할 수 있는 강력한 도구입니다.
핵심 포인트:
- 다양한 패키지 형식 지원
- GitHub Actions와 완벽한 통합
- 세분화된 권한 관리
- 프라이빗 패키지 지원
- 통합된 보안 스캔
소스 코드와 패키지를 함께 관리하여 개발 워크플로우를 간소화하고 보안을 강화하세요.
다음 편에서는 Codespaces를 활용한 클라우드 개발 환경에 대해 알아보겠습니다.
📚 GitHub 마스터하기 시리즈
🌱 기초편 (입문자)
- GitHub 시작하기
- Repository 기초
- Git 기본 명령어
- Branch와 Merge
- Fork와 Pull Request
💼 실전편 (중급자)
- Issues 활용법
- Projects로 프로젝트 관리
- Code Review 잘하기
- GitHub Discussions
- Team 협업 설정
- GitHub Pages
🚀 고급편 (전문가)
- GitHub Actions 입문
- Actions 고급 활용
- Webhooks와 API
- GitHub Apps 개발
- 보안 기능
- [GitHub Packages] (현재 글)(/posts/github-advanced-06-github-packages/)
- Codespaces
- GitHub CLI
- 통계와 인사이트
🏆 심화편 (전문가+)
- Git Submodules & Subtree
- Git 내부 동작 원리
- 고급 브랜치 전략과 릴리스 관리
- GitHub GraphQL API
-