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
+
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