Publish pfSense ISO #32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish pfSense ISO | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: '0 2 * * 1' | |
| env: | |
| PFSENSE_BASE_URL: https://atxfiles.netgate.com/mirror/downloads | |
| jobs: | |
| download-and-release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Discover latest pfSense version | |
| id: discover | |
| run: | | |
| set -euo pipefail | |
| echo "π Discovering latest pfSense version..." | |
| # Fetch and parse latest version | |
| LATEST_FILE=$(curl -fsSL "$PFSENSE_BASE_URL/" | \ | |
| grep -oP 'pfSense-CE-\d+\.\d+\.\d+-RELEASE-amd64\.iso\.gz' | \ | |
| sort -V | tail -n1) | |
| if [[ -z "$LATEST_FILE" ]]; then | |
| echo "β Failed to find pfSense ISO file" | |
| exit 1 | |
| fi | |
| VERSION=$(echo "$LATEST_FILE" | sed 's/pfSense-CE-\(.*\)-RELEASE-amd64\.iso\.gz/\1/') | |
| ISO_FILE="${LATEST_FILE%.gz}" | |
| SHA_FILE="${ISO_FILE}.sha256" | |
| echo "π¦ Found version: $VERSION" | |
| echo "π ISO file: $ISO_FILE" | |
| # Export variables | |
| { | |
| echo "latest_file=$LATEST_FILE" | |
| echo "version=$VERSION" | |
| echo "iso_file=$ISO_FILE" | |
| echo "sha_file=$SHA_FILE" | |
| echo "download_url=$PFSENSE_BASE_URL/$LATEST_FILE" | |
| echo "checksum_url=$PFSENSE_BASE_URL/$LATEST_FILE.sha256" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Check if release already exists | |
| id: check_release | |
| run: | | |
| set +e # Don't exit on error for this check | |
| echo "π Checking if release ${{ steps.discover.outputs.version }} already exists..." | |
| gh release view "${{ steps.discover.outputs.version }}" >/dev/null 2>&1 | |
| EXISTS=$? | |
| if [[ $EXISTS -eq 0 ]]; then | |
| echo "β Release already exists, skipping..." | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "π New release detected, proceeding..." | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Download pfSense files | |
| if: steps.check_release.outputs.skip == 'false' | |
| run: | | |
| set -euo pipefail | |
| echo "β¬οΈ Downloading pfSense ${{ steps.discover.outputs.version }}..." | |
| # Download with progress and retry logic | |
| download_with_retry() { | |
| local url="$1" | |
| local max_attempts=3 | |
| local attempt=1 | |
| while [[ $attempt -le $max_attempts ]]; do | |
| echo "π₯ Attempt $attempt/$max_attempts: $(basename "$url")" | |
| if curl -fsSL --progress-bar --retry 3 --retry-delay 5 -o "$(basename "$url")" "$url"; then | |
| return 0 | |
| fi | |
| ((attempt++)) | |
| sleep 10 | |
| done | |
| echo "β Failed to download $url after $max_attempts attempts" | |
| return 1 | |
| } | |
| download_with_retry "${{ steps.discover.outputs.download_url }}" | |
| download_with_retry "${{ steps.discover.outputs.checksum_url }}" | |
| - name: Verify integrity | |
| if: steps.check_release.outputs.skip == 'false' | |
| run: | | |
| set -euo pipefail | |
| echo "π Verifying file integrity..." | |
| # Verify the compressed file first | |
| if sha256sum -c "${{ steps.discover.outputs.latest_file }}.sha256"; then | |
| echo "β Compressed file integrity verified" | |
| else | |
| echo "β Compressed file integrity check failed" | |
| exit 1 | |
| fi | |
| - name: Extract ISO | |
| if: steps.check_release.outputs.skip == 'false' | |
| run: | | |
| set -euo pipefail | |
| echo "π¦ Extracting ISO file..." | |
| # Extract with progress | |
| gunzip -v "${{ steps.discover.outputs.latest_file }}" | |
| # Verify extraction | |
| if [[ -f "${{ steps.discover.outputs.iso_file }}" ]]; then | |
| ISO_SIZE=$(du -h "${{ steps.discover.outputs.iso_file }}" | cut -f1) | |
| echo "β Extraction complete - ISO size: $ISO_SIZE" | |
| else | |
| echo "β ISO extraction failed" | |
| exit 1 | |
| fi | |
| - name: Generate checksums | |
| if: steps.check_release.outputs.skip == 'false' | |
| run: | | |
| set -euo pipefail | |
| echo "π Generating checksums for extracted ISO..." | |
| # Generate multiple checksums for verification | |
| sha256sum "${{ steps.discover.outputs.iso_file }}" > "${{ steps.discover.outputs.sha_file }}" | |
| md5sum "${{ steps.discover.outputs.iso_file }}" > "${{ steps.discover.outputs.iso_file }}.md5" | |
| # Display checksums | |
| echo "π Generated checksums:" | |
| echo "SHA256: $(cat "${{ steps.discover.outputs.sha_file }}")" | |
| echo "MD5: $(cat "${{ steps.discover.outputs.iso_file }}.md5")" | |
| - name: Create GitHub Release | |
| if: steps.check_release.outputs.skip == 'false' | |
| run: | | |
| set -euo pipefail | |
| echo "π Creating GitHub release..." | |
| # Create release with detailed body | |
| RELEASE_BODY="## pfSense Community Edition ${{ steps.discover.outputs.version }} | |
| This is an automated release of pfSense CE ${{ steps.discover.outputs.version }}. | |
| ### Files included: | |
| - π― **${{ steps.discover.outputs.iso_file }}** - Main ISO image | |
| - π **${{ steps.discover.outputs.sha_file }}** - SHA256 checksum | |
| - π **${{ steps.discover.outputs.iso_file }}.md5** - MD5 checksum | |
| ### Verification: | |
| \`\`\`bash | |
| # Verify SHA256 | |
| sha256sum -c ${{ steps.discover.outputs.sha_file }} | |
| # Verify MD5 | |
| md5sum -c ${{ steps.discover.outputs.iso_file }}.md5 | |
| \`\`\` | |
| ### Source: | |
| Downloaded from: [Netgate Official Mirror](${{ env.PFSENSE_BASE_URL }}) | |
| --- | |
| *Automated release created on $(date -u '+%Y-%m-%d %H:%M:%S UTC')*" | |
| gh release create "${{ steps.discover.outputs.version }}" \ | |
| --title "pfSense CE ${{ steps.discover.outputs.version }}" \ | |
| --notes "$RELEASE_BODY" \ | |
| "${{ steps.discover.outputs.iso_file }}" \ | |
| "${{ steps.discover.outputs.sha_file }}" \ | |
| "${{ steps.discover.outputs.iso_file }}.md5" | |
| echo "β Release created successfully!" | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Clean up artifacts | |
| if: always() | |
| run: | | |
| echo "π§Ή Cleaning up downloaded files..." | |
| rm -f *.iso *.gz *.sha256 *.md5 || true | |
| echo "β Cleanup complete" | |
| - name: Release summary | |
| if: steps.check_release.outputs.skip == 'false' | |
| run: | | |
| echo "## π pfSense Release Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Version:** ${{ steps.discover.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**ISO File:** ${{ steps.discover.outputs.iso_file }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Release URL:** ${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ steps.discover.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "β Release created successfully!" >> $GITHUB_STEP_SUMMARY |