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