@@ -50,11 +50,48 @@ jobs:
5050 - name : Create package directory structure
5151 run : |
5252 mkdir -p upload/simple/${{ env.PACKAGE_NAME }}
53+ mkdir -p upload/versions/${{ steps.get_version.outputs.VERSION }}
5354
54- - name : Copy package files
55+ - name : Copy package files to version-specific folder
5556 run : |
57+ cp dist/* upload/versions/${{ steps.get_version.outputs.VERSION }}/
58+
59+ - name : List existing versions from S3
60+ id : list_versions
61+ run : |
62+ # Get existing versions from S3 (ignore errors if bucket is empty)
63+ aws s3 ls s3://${{ secrets.S3_BUCKET_NAME }}/versions/ || true > existing_versions.txt
64+
65+ # Extract version numbers and add current version
66+ VERSIONS=$(awk '{print $2}' existing_versions.txt | sed 's/\///g' | sort -V)
67+ CURRENT_VERSION="${{ steps.get_version.outputs.VERSION }}"
68+
69+ # Combine existing and current versions, remove duplicates, and sort
70+ ALL_VERSIONS=$(echo -e "$VERSIONS\n$CURRENT_VERSION" | sort -V | uniq)
71+
72+ echo "Available versions:"
73+ echo "$ALL_VERSIONS"
74+
75+ # Save for use in HTML generation
76+ echo "$ALL_VERSIONS" > all_versions.txt
77+
78+ # Format for JSON array (for potential future use)
79+ VERSIONS_JSON=$(echo "$ALL_VERSIONS" | jq -R . | jq -s .)
80+ echo "VERSIONS_JSON=$VERSIONS_JSON" >> $GITHUB_OUTPUT
81+
82+ - name : Copy package files to simple index (all versions)
83+ run : |
84+ # Copy current version to simple index
5685 cp dist/* upload/simple/${{ env.PACKAGE_NAME }}/
5786
87+ # Download and copy existing versions from S3
88+ while IFS= read -r version; do
89+ if [ ! -z "$version" ] && [ "$version" != "${{ steps.get_version.outputs.VERSION }}" ]; then
90+ echo "Downloading version $version"
91+ aws s3 sync s3://${{ secrets.S3_BUCKET_NAME }}/versions/$version/ upload/simple/${{ env.PACKAGE_NAME }}/ || echo "Version $version not found in S3"
92+ fi
93+ done < all_versions.txt
94+
5895 - name : Generate package index HTML
5996 run : |
6097 cat > upload/simple/${{ env.PACKAGE_NAME }}/index.html << EOF
65102 </head>
66103 <body>
67104 <h1>Links for ${{ env.PACKAGE_NAME }}</h1>
105+ <p><a href="../../versions.html">View all versions</a></p>
68106 EOF
69107
70108 for file in upload/simple/${{ env.PACKAGE_NAME }}/*.{tar.gz,whl}; do
@@ -76,6 +114,70 @@ jobs:
76114
77115 echo "</body></html>" >> upload/simple/${{ env.PACKAGE_NAME }}/index.html
78116
117+ - name : Generate versions page HTML
118+ run : |
119+ cat > upload/versions.html << EOF
120+ <!DOCTYPE html>
121+ <html>
122+ <head>
123+ <title>All Versions of ${{ env.PACKAGE_NAME }}</title>
124+ <style>
125+ body { font-family: Arial, sans-serif; margin: 40px; }
126+ .version { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
127+ .version h3 { margin-top: 0; color: #333; }
128+ .files { margin-left: 20px; }
129+ .current { background-color: #e8f5e8; border-color: #4caf50; }
130+ .install-cmd { background-color: #f5f5f5; padding: 10px; border-radius: 3px; font-family: monospace; }
131+ </style>
132+ </head>
133+ <body>
134+ <h1>All Versions of ${{ env.PACKAGE_NAME }}</h1>
135+ <p>Available versions of the ${{ env.PACKAGE_NAME }} package.</p>
136+
137+ <div class="install-cmd">
138+ <strong>Install latest:</strong> pip install ${{ env.PACKAGE_NAME }} --index-url https://${{ secrets.CLOUDFRONT_DOMAIN }}/simple/<br/>
139+ <strong>Install specific version:</strong> pip install ${{ env.PACKAGE_NAME }}==VERSION --index-url https://${{ secrets.CLOUDFRONT_DOMAIN }}/simple/
140+ </div>
141+ EOF
142+
143+ # Generate version listings
144+ while IFS= read -r version; do
145+ if [ ! -z "$version" ]; then
146+ echo "Processing version: $version"
147+
148+ # Check if this is the current version
149+ CURRENT_CLASS=""
150+ if [ "$version" = "${{ steps.get_version.outputs.VERSION }}" ]; then
151+ CURRENT_CLASS=" current"
152+ fi
153+
154+ cat >> upload/versions.html << EOF
155+ <div class="version$CURRENT_CLASS">
156+ <h3>Version $version</h3>
157+ EOF
158+
159+ if [ "$version" = "${{ steps.get_version.outputs.VERSION }}" ]; then
160+ echo " <p><strong>(Current/Latest Version)</strong></p>" >> upload/versions.html
161+ fi
162+
163+ echo " <div class=\"files\">" >> upload/versions.html
164+ echo " <strong>Available files:</strong><br/>" >> upload/versions.html
165+
166+ # List files for this version
167+ for file in upload/versions/$version/*.{tar.gz,whl}; do
168+ if [ -f "$file" ]; then
169+ filename=$(basename "$file")
170+ echo " <a href=\"versions/$version/$filename\">$filename</a><br/>" >> upload/versions.html
171+ fi
172+ done
173+
174+ echo " </div>" >> upload/versions.html
175+ echo "</div>" >> upload/versions.html
176+ fi
177+ done < all_versions.txt
178+
179+ echo "</body></html>" >> upload/versions.html
180+
79181 - name : Generate main simple index
80182 run : |
81183 cat > upload/simple/index.html << EOF
@@ -98,20 +200,50 @@ jobs:
98200 <html>
99201 <head>
100202 <title>LayerLens Python Package Repository</title>
203+ <style>
204+ body { font-family: Arial, sans-serif; margin: 40px; }
205+ .install-cmd { background-color: #f5f5f5; padding: 15px; border-radius: 5px; font-family: monospace; margin: 20px 0; }
206+ .links { margin: 20px 0; }
207+ .links a { display: inline-block; margin-right: 20px; padding: 10px 15px; background-color: #007cba; color: white; text-decoration: none; border-radius: 3px; }
208+ .links a:hover { background-color: #005a87; }
209+ </style>
101210 </head>
102211 <body>
103212 <h1>LayerLens Python Package Repository</h1>
104213 <p>Custom Python package repository for ${{ env.PACKAGE_NAME }}</p>
105- <p><a href="simple/">Browse packages</a></p>
214+
215+ <div class="links">
216+ <a href="simple/">Browse packages</a>
217+ <a href="versions.html">View all versions</a>
218+ </div>
219+
106220 <h2>Installation</h2>
107- <pre>pip install ${{ env.PACKAGE_NAME }} --index-url https://${{ secrets.CLOUDFRONT_DOMAIN }}/simple/</pre>
221+ <div class="install-cmd">
222+ # Install latest version<br/>
223+ pip install ${{ env.PACKAGE_NAME }} --index-url https://${{ secrets.CLOUDFRONT_DOMAIN }}/simple/<br/><br/>
224+
225+ # Install specific version<br/>
226+ pip install ${{ env.PACKAGE_NAME }}==1.0.0 --index-url https://${{ secrets.CLOUDFRONT_DOMAIN }}/simple/
227+ </div>
228+
229+ <h2>Current Version</h2>
230+ <p>Latest version: <strong>${{ steps.get_version.outputs.VERSION }}</strong></p>
108231 </body>
109232 </html>
110233 EOF
111234
112235 - name : Upload to S3
113236 run : |
114- aws s3 sync upload/ s3://${{ secrets.S3_BUCKET_NAME }}/ --delete
237+ # Upload everything except we don't want to delete old versions
238+ # Upload the simple index (with --delete to clean up old files)
239+ aws s3 sync upload/simple/ s3://${{ secrets.S3_BUCKET_NAME }}/simple/ --delete
240+
241+ # Upload version-specific files (without --delete to preserve old versions)
242+ aws s3 sync upload/versions/ s3://${{ secrets.S3_BUCKET_NAME }}/versions/
243+
244+ # Upload main pages (index.html, versions.html)
245+ aws s3 cp upload/index.html s3://${{ secrets.S3_BUCKET_NAME }}/index.html
246+ aws s3 cp upload/versions.html s3://${{ secrets.S3_BUCKET_NAME }}/versions.html
115247
116248 - name : Invalidate CloudFront cache
117249 run : |
0 commit comments