1+ name : PR Preview
2+ on :
3+ pull_request :
4+ types : [opened, synchronize]
5+
6+ jobs :
7+ preview :
8+ runs-on : ubuntu-latest
9+ steps :
10+ - uses : actions/checkout@v4
11+ - uses : actions/setup-python@v5
12+ with :
13+ python-version : ' 3.x'
14+
15+ # Install all dependencies from pyproject.toml
16+ - name : Install dependencies
17+ run : |
18+ python -m pip install --upgrade pip
19+ pip install -e .
20+
21+ - name : Set preview version
22+ run : |
23+ BASE_VERSION=$(python -c "from socketsecurity import __version__; print(__version__)")
24+ PREVIEW_VERSION="${BASE_VERSION}.dev${{ github.event.pull_request.number }}${{ github.event.pull_request.commits }}"
25+ echo "VERSION=${PREVIEW_VERSION}" >> $GITHUB_ENV
26+
27+ # Update version in __init__.py
28+ echo "__version__ = \"${PREVIEW_VERSION}\"" > socketsecurity/__init__.py.tmp
29+ cat socketsecurity/__init__.py | grep -v "__version__" >> socketsecurity/__init__.py.tmp
30+ mv socketsecurity/__init__.py.tmp socketsecurity/__init__.py
31+
32+ # Verify the change
33+ echo "Updated version in __init__.py:"
34+ python -c "from socketsecurity import __version__; print(__version__)"
35+
36+ - name : Check if version exists on Test PyPI
37+ id : version_check
38+ env :
39+ VERSION : ${{ env.VERSION }}
40+ run : |
41+ if curl -s -f https://test.pypi.org/pypi/socketsecurity/$VERSION/json > /dev/null; then
42+ echo "Version ${VERSION} already exists on Test PyPI"
43+ echo "exists=true" >> $GITHUB_OUTPUT
44+ else
45+ echo "Version ${VERSION} not found on Test PyPI"
46+ echo "exists=false" >> $GITHUB_OUTPUT
47+ fi
48+
49+ - name : Build package
50+ if : steps.version_check.outputs.exists != 'true'
51+ run : |
52+ pip install build
53+ python -m build
54+
55+ - name : Restore original version
56+ if : always()
57+ run : |
58+ BASE_VERSION=$(echo $VERSION | cut -d'.' -f1-3)
59+ echo "__version__ = \"${BASE_VERSION}\"" > socketsecurity/__init__.py.tmp
60+ cat socketsecurity/__init__.py | grep -v "__version__" >> socketsecurity/__init__.py.tmp
61+ mv socketsecurity/__init__.py.tmp socketsecurity/__init__.py
62+
63+ - name : Publish to Test PyPI
64+ if : steps.version_check.outputs.exists != 'true'
65+ uses : pypa/gh-action-pypi-publish@v1.8.11
66+ with :
67+ repository-url : https://test.pypi.org/legacy/
68+ password : ${{ secrets.TEST_PYPI_TOKEN }}
69+ verbose : true
70+
71+ - name : Comment on PR
72+ if : steps.version_check.outputs.exists != 'true'
73+ uses : actions/github-script@v7
74+ env :
75+ VERSION : ${{ env.VERSION }}
76+ with :
77+ script : |
78+ const version = process.env.VERSION;
79+ const prNumber = context.payload.pull_request.number;
80+ const owner = context.repo.owner;
81+ const repo = context.repo.repo;
82+ // Find existing bot comments
83+ const comments = await github.rest.issues.listComments({
84+ owner: context.repo.owner,
85+ repo: context.repo.repo,
86+ issue_number: prNumber,
87+ });
88+
89+ const botComment = comments.data.find(comment =>
90+ comment.user.type === 'Bot' &&
91+ comment.body.includes('🚀 Preview package published!')
92+ );
93+
94+ const comment = `
95+ 🚀 Preview package published!
96+
97+ Install with:
98+ \`\`\`bash
99+ pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple socketsecurity==${version}
100+ \`\`\`
101+
102+ Docker image: \`socketdev/cli:pr-${prNumber}\`
103+ `;
104+
105+ if (botComment) {
106+ // Update existing comment
107+ await github.rest.issues.updateComment({
108+ owner: owner,
109+ repo: repo,
110+ comment_id: botComment.id,
111+ body: comment
112+ });
113+ } else {
114+ // Create new comment
115+ await github.rest.issues.createComment({
116+ owner: owner,
117+ repo: repo,
118+ issue_number: prNumber,
119+ body: comment
120+ });
121+ }
122+
123+ - name : Verify package is available
124+ if : steps.version_check.outputs.exists != 'true'
125+ id : verify_package
126+ env :
127+ VERSION : ${{ env.VERSION }}
128+ run : |
129+ for i in {1..30}; do
130+ if pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple socketsecurity==${VERSION}; then
131+ echo "Package ${VERSION} is now available and installable on Test PyPI"
132+ pip uninstall -y socketsecurity
133+ echo "success=true" >> $GITHUB_OUTPUT
134+ exit 0
135+ fi
136+ echo "Attempt $i: Package not yet installable, waiting 20s... (${i}/30)"
137+ sleep 20
138+ done
139+ echo "success=false" >> $GITHUB_OUTPUT
140+ exit 1
141+
142+ - name : Login to Docker Hub
143+ if : steps.verify_package.outputs.success == 'true'
144+ uses : docker/login-action@v3
145+ with :
146+ username : ${{ secrets.DOCKERHUB_USERNAME }}
147+ password : ${{ secrets.DOCKERHUB_TOKEN }}
148+
149+ - name : Set up QEMU
150+ uses : docker/setup-qemu-action@v3
151+
152+ - name : Set up Docker Buildx
153+ uses : docker/setup-buildx-action@v3
154+
155+ - name : Build & Push Docker Preview
156+ if : steps.verify_package.outputs.success == 'true'
157+ uses : docker/build-push-action@v5
158+ env :
159+ VERSION : ${{ env.VERSION }}
160+ with :
161+ push : true
162+ platforms : linux/amd64,linux/arm64
163+ tags : |
164+ socketdev/cli:pr-${{ github.event.pull_request.number }}
165+ build-args : |
166+ CLI_VERSION=${{ env.VERSION }}
167+ PIP_INDEX_URL=https://test.pypi.org/simple
168+ PIP_EXTRA_INDEX_URL=https://pypi.org/simple
0 commit comments