Skip to content

Commit abbe82d

Browse files
authored
Merge pull request #798 from atlanhq/chore/snyk-deps-requirements
chore(ci): add Harbor publish + Snyk deps support
2 parents 1a06403 + 5246e84 commit abbe82d

7 files changed

Lines changed: 713 additions & 223 deletions

File tree

.github/workflows/pyatlan-chainguard.yaml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ jobs:
5757
username: ${{ github.actor }}
5858
password: ${{ secrets.GITHUB_TOKEN }}
5959

60+
- name: Log in to Atlan Harbor Registry
61+
uses: docker/login-action@v3
62+
with:
63+
registry: registry.atlan.com
64+
username: ${{ secrets.HARBOR_USERNAME }}
65+
password: ${{ secrets.HARBOR_PASSWORD }}
66+
6067
- name: Log in to Chainguard Container Registry
6168
uses: docker/login-action@v3
6269
with:
@@ -84,7 +91,7 @@ jobs:
8491
else
8592
PYTHON_VERSION="${{ github.event.inputs.python_version }}"
8693
fi
87-
94+
8895
# Set Pyatlan version (reads from pyatlan/version.txt by default)
8996
# This matches the version in the repository
9097
if [ -z "${{ github.event.inputs.pyatlan_version }}" ]; then
@@ -94,7 +101,7 @@ jobs:
94101
PYATLAN_VERSION="${{ github.event.inputs.pyatlan_version }}"
95102
echo "Using specified pyatlan version: $PYATLAN_VERSION"
96103
fi
97-
104+
98105
# Handle branch input (if provided, will be used as commit SHA or branch name)
99106
if [ -n "${{ github.event.inputs.pyatlan_branch }}" ]; then
100107
echo "Note: Building from branch/commit: ${{ github.event.inputs.pyatlan_branch }}"
@@ -105,27 +112,27 @@ jobs:
105112
echo "BUILD_TYPE=$BUILD_TYPE" >> $GITHUB_ENV
106113
echo "PYTHON_VERSION=$PYTHON_VERSION" >> $GITHUB_ENV
107114
echo "PYATLAN_VERSION=$PYATLAN_VERSION" >> $GITHUB_ENV
108-
115+
109116
# Set platforms based on build type
110117
if [ "$BUILD_TYPE" = "dev" ]; then
111118
PLATFORMS="linux/amd64"
112119
else
113120
PLATFORMS="linux/amd64,linux/arm64"
114121
fi
115122
echo "PLATFORMS=$PLATFORMS" >> $GITHUB_ENV
116-
123+
117124
# Generate commit hash for dev builds (for image tagging only)
118125
COMMIT_HASH=$(git rev-parse --short HEAD)
119126
echo "COMMIT_HASH=$COMMIT_HASH" >> $GITHUB_ENV
120-
127+
121128
# Set PYATLAN_COMMIT_SHA only if pyatlan_branch input is provided
122129
# Otherwise, leave empty to let Dockerfile use version tag
123130
if [ -n "${{ github.event.inputs.pyatlan_branch }}" ]; then
124131
echo "PYATLAN_COMMIT_SHA=${{ github.event.inputs.pyatlan_branch }}" >> $GITHUB_ENV
125132
else
126133
echo "PYATLAN_COMMIT_SHA=" >> $GITHUB_ENV
127134
fi
128-
135+
129136
echo "Build parameters:"
130137
echo " - Trigger: ${{ github.event_name }}"
131138
echo " - Build Type: $BUILD_TYPE"
@@ -150,12 +157,17 @@ jobs:
150157
if [ "$BUILD_TYPE" = "dev" ]; then
151158
# Dev: 8.0.0-3.11-commithash
152159
IMAGE_TAG="${PYATLAN_VERSION}-${PYTHON_VERSION}-${COMMIT_HASH}"
160+
HARBOR_TAGS="registry.atlan.com/public/pyatlan:${IMAGE_TAG}\nregistry.atlan.com/public/pyatlan:sha-${COMMIT_HASH}"
153161
else
154162
# Release: 8.0.0-3.11
155163
IMAGE_TAG="${PYATLAN_VERSION}-${PYTHON_VERSION}"
164+
HARBOR_TAGS="registry.atlan.com/public/pyatlan:${IMAGE_TAG}\nregistry.atlan.com/public/pyatlan:main-latest\nregistry.atlan.com/public/pyatlan:main-${PYATLAN_VERSION}\nregistry.atlan.com/public/pyatlan:sha-${COMMIT_HASH}"
156165
fi
157166
158167
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
168+
echo "HARBOR_TAGS<<EOF" >> $GITHUB_ENV
169+
echo -e "$HARBOR_TAGS" >> $GITHUB_ENV
170+
echo "EOF" >> $GITHUB_ENV
159171
160172
echo "Generated image tag: ghcr.io/atlanhq/pyatlan-chainguard-base:$IMAGE_TAG"
161173
@@ -168,6 +180,7 @@ jobs:
168180
push: true
169181
tags: |
170182
ghcr.io/atlanhq/pyatlan-chainguard-base:${{ env.IMAGE_TAG }}
183+
${{ env.HARBOR_TAGS }}
171184
build-args: |
172185
PYTHON_VERSION=${{ env.PYTHON_VERSION }}
173186
PYATLAN_VERSION=${{ env.PYATLAN_VERSION }}

.github/workflows/trivy.yml

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
name: Trivy Image and Dependency Scan
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
branches: [main]
7+
push:
8+
branches: [main]
9+
10+
permissions:
11+
contents: read
12+
pull-requests: write
13+
actions: read
14+
security-events: write
15+
16+
jobs:
17+
trivy:
18+
runs-on: ubuntu-latest
19+
timeout-minutes: 20
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Set up Docker Buildx
25+
uses: docker/setup-buildx-action@v3
26+
27+
- name: Log in to Chainguard Container Registry
28+
uses: docker/login-action@v3
29+
with:
30+
registry: cgr.dev
31+
username: ${{ secrets.CHAINGUARD_USERNAME }}
32+
password: ${{ secrets.CHAINGUARD_PASSWORD }}
33+
34+
- name: Build image
35+
uses: docker/build-push-action@v6
36+
with:
37+
context: .
38+
file: ./Dockerfile
39+
push: false
40+
load: true
41+
tags: pyatlan-trivy:latest
42+
43+
- name: Trivy image scan (table)
44+
uses: aquasecurity/trivy-action@0.33.1
45+
with:
46+
image-ref: pyatlan-trivy:latest
47+
scanners: 'vuln'
48+
version: 'v0.69.0'
49+
ignore-unfixed: true
50+
format: 'table'
51+
output: 'trivy-image.txt'
52+
severity: 'CRITICAL,HIGH'
53+
exit-code: '0'
54+
env:
55+
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
56+
TRIVY_JAVA_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-java-db:1
57+
58+
- name: Show Trivy image table
59+
if: always()
60+
shell: bash
61+
run: |
62+
echo "Trivy image scan (table)";
63+
if [ -f trivy-image.txt ]; then
64+
cat trivy-image.txt;
65+
else
66+
echo "No trivy-image.txt output found.";
67+
fi
68+
69+
- name: Trivy image scan (SARIF)
70+
uses: aquasecurity/trivy-action@0.33.1
71+
with:
72+
image-ref: pyatlan-trivy:latest
73+
scanners: 'vuln'
74+
version: 'v0.69.0'
75+
ignore-unfixed: true
76+
format: 'sarif'
77+
output: 'trivy-image.sarif'
78+
severity: 'CRITICAL,HIGH'
79+
exit-code: '0'
80+
env:
81+
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
82+
TRIVY_JAVA_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-java-db:1
83+
84+
- name: Trivy dependency scan (uv.lock, table)
85+
uses: aquasecurity/trivy-action@0.33.1
86+
with:
87+
scan-type: fs
88+
scan-ref: uv.lock
89+
scanners: 'vuln'
90+
version: 'v0.69.0'
91+
ignore-unfixed: true
92+
format: 'table'
93+
output: 'trivy-deps.txt'
94+
severity: 'CRITICAL,HIGH'
95+
exit-code: '0'
96+
env:
97+
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
98+
99+
- name: Show Trivy dependency table
100+
if: always()
101+
shell: bash
102+
run: |
103+
echo "Trivy dependency scan (table)";
104+
if [ -f trivy-deps.txt ]; then
105+
cat trivy-deps.txt;
106+
else
107+
echo "No trivy-deps.txt output found.";
108+
fi
109+
110+
- name: Trivy dependency scan (uv.lock, SARIF)
111+
uses: aquasecurity/trivy-action@0.33.1
112+
with:
113+
scan-type: fs
114+
scan-ref: uv.lock
115+
scanners: 'vuln'
116+
version: 'v0.69.0'
117+
ignore-unfixed: true
118+
format: 'sarif'
119+
output: 'trivy-deps.sarif'
120+
severity: 'CRITICAL,HIGH'
121+
exit-code: '0'
122+
env:
123+
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
124+
125+
- name: Upload Trivy image results
126+
if: github.event.repository.security_and_analysis.advanced_security.status == 'enabled'
127+
uses: github/codeql-action/upload-sarif@v3
128+
with:
129+
sarif_file: 'trivy-image.sarif'
130+
category: 'trivy-image'
131+
132+
- name: Upload Trivy dependency results
133+
if: github.event.repository.security_and_analysis.advanced_security.status == 'enabled'
134+
uses: github/codeql-action/upload-sarif@v3
135+
with:
136+
sarif_file: 'trivy-deps.sarif'
137+
category: 'trivy-deps'
138+
139+
- name: Publish Trivy summary
140+
if: always()
141+
shell: bash
142+
run: |
143+
{
144+
echo "## Trivy Image Scan (pyatlan-trivy:latest)";
145+
echo "";
146+
if [ -f trivy-image.txt ]; then
147+
echo '```';
148+
cat trivy-image.txt;
149+
echo '```';
150+
else
151+
echo "No image scan output found.";
152+
fi
153+
echo "";
154+
echo "## Trivy Dependency Scan (uv.lock)";
155+
echo "";
156+
if [ -f trivy-deps.txt ]; then
157+
echo '```';
158+
cat trivy-deps.txt;
159+
echo '```';
160+
else
161+
echo "No dependency scan output found.";
162+
fi
163+
} >> "$GITHUB_STEP_SUMMARY"
164+
165+
- name: Fail on High/Critical vulnerabilities (image)
166+
uses: aquasecurity/trivy-action@0.33.1
167+
with:
168+
image-ref: pyatlan-trivy:latest
169+
scanners: 'vuln'
170+
version: 'v0.69.0'
171+
ignore-unfixed: true
172+
format: 'table'
173+
severity: 'CRITICAL,HIGH'
174+
exit-code: '1'
175+
env:
176+
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
177+
TRIVY_JAVA_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-java-db:1
178+
179+
- name: Fail on High/Critical vulnerabilities (uv.lock)
180+
uses: aquasecurity/trivy-action@0.33.1
181+
with:
182+
scan-type: fs
183+
scan-ref: uv.lock
184+
scanners: 'vuln'
185+
version: 'v0.69.0'
186+
ignore-unfixed: true
187+
format: 'table'
188+
severity: 'CRITICAL,HIGH'
189+
exit-code: '1'
190+
env:
191+
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2

.pre-commit-config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,9 @@ repos:
2525
types: [python]
2626
pass_filenames: false
2727
stages: [manual]
28+
- id: sync-requirements
29+
name: sync-requirements
30+
entry: bash -c "uv export --all-extras --no-hashes > requirements.txt"
31+
language: system
32+
pass_filenames: false
33+
files: ^uv.lock$

README.md

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
[![Downloads](https://img.shields.io/pypi/dm/pyatlan.svg)](https://pypi.org/project/pyatlan/)
1111
[![Build Status](https://github.com/atlanhq/atlan-python/actions/workflows/pyatlan-publish.yaml/badge.svg)](https://github.com/atlanhq/atlan-python/actions/workflows/pyatlan-publish.yaml)
1212
[![Documentation](https://img.shields.io/badge/docs-developer.atlan.com-blue.svg)](https://developer.atlan.com/getting-started/python-sdk/)
13-
[![Docker](https://img.shields.io/badge/docker-ghcr.io%2Fatlanhq%2Fatlan--python-blue.svg)](https://github.com/atlanhq/atlan-python/pkgs/container/atlan-python)
13+
[![Docker](https://img.shields.io/badge/docker-harbor-blue.svg)](https://registry.atlan.com/)
1414

1515
---
1616

@@ -84,32 +84,44 @@ uv sync --all-groups
8484

8585
## 🐳 Docker
8686

87-
### Pre-built Images
88-
87+
### Pre-built Images (Harbor)
8988

9089
```bash
91-
# Latest version
92-
docker pull ghcr.io/atlanhq/atlan-python:latest
90+
# Latest main image
91+
docker pull registry.atlan.com/public/pyatlan:main-latest
9392

94-
# Specific version
95-
docker pull ghcr.io/atlanhq/atlan-python:7.1.3
93+
# Version + Python tag
94+
docker pull registry.atlan.com/public/pyatlan:8.5.1-3.11
95+
96+
# Commit-specific image
97+
docker pull registry.atlan.com/public/pyatlan:sha-1a064032
9698
```
9799

98100
### Usage
99101

100102
```bash
101103
# Interactive Python session
102-
docker run -it --rm ghcr.io/atlanhq/atlan-python:latest
104+
docker run -it --rm registry.atlan.com/public/pyatlan:main-latest
103105

104106
# Run a script
105107
docker run -it --rm \
106108
-v $(pwd):/app \
107109
-e ATLAN_API_KEY=your_key \
108110
-e ATLAN_BASE_URL=https://your-tenant.atlan.com \
109-
ghcr.io/atlanhq/atlan-python:latest \
111+
registry.atlan.com/public/pyatlan:main-latest \
110112
python your_script.py
111113
```
112114

115+
## 🔒 Security Scans
116+
117+
### Run Snyk locally (dependencies)
118+
119+
```bash
120+
uv export --all-extras --no-hashes > requirements.txt
121+
snyk test --file=requirements.txt --severity-threshold=high --skip-unresolved
122+
rm -f requirements.txt
123+
```
124+
113125
## 🧪 Testing
114126

115127
### Unit Tests

pyproject.toml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ dependencies = [
3737
"PyYAML~=6.0.3",
3838
"httpx~=0.28.1",
3939
"httpx-retries~=0.4.5",
40-
"authlib~=1.6.5",
40+
"authlib~=1.6.6",
4141
]
4242

4343
[project.urls]
@@ -52,6 +52,10 @@ dev = [
5252
"ruff~=0.14.5",
5353
"types-setuptools~=80.9.0.20250822",
5454
"types-Authlib~=1.6.5.20251005",
55+
"jaraco-context~=6.1.0",
56+
"filelock~=3.20.3; python_version >= '3.10'",
57+
"virtualenv~=20.36.1",
58+
"urllib3~=2.6.3; python_version >= '3.10'",
5559
"pytest~=8.4.2",
5660
"pytest-vcr~=1.0.2",
5761
"vcrpy~=7.0.0",
@@ -114,3 +118,9 @@ asyncio_default_fixture_loop_scope = "module"
114118
filterwarnings = [
115119
"ignore::DeprecationWarning",
116120
]
121+
122+
[tool.uv]
123+
environments = ["python_version >= '3.9' and python_version < '3.14' and platform_python_implementation == 'CPython'"]
124+
125+
[tool.poe.tasks]
126+
snyk-requirements = "uv export --all-extras --no-hashes > snyk-requirements.txt"

0 commit comments

Comments
 (0)