diff --git a/.github/workflows/providers/gitea-release.yml b/.github/workflows/providers/gitea-release.yml index c7aaafd..95ff349 100644 --- a/.github/workflows/providers/gitea-release.yml +++ b/.github/workflows/providers/gitea-release.yml @@ -1,7 +1,14 @@ name: Gitea Release on: - workflow_call: # This workflow will only be triggered when called by another workflow + workflow_call: + inputs: + version: + required: true + type: string + changelog: + required: true + type: string permissions: contents: write # Required for creating releases @@ -21,19 +28,17 @@ jobs: with: python-version: '3.x' - - name: Install PlatformIO + - name: Install dependencies run: | python -m pip install --upgrade pip - pip install --upgrade platformio + pip install --upgrade platformio esptool + sudo apt-get update + sudo apt-get install -y jq - name: Build Firmware run: | - pio run -t buildfs # Build SPIFFS - pio run # Build firmware - - - name: Install esptool - run: | - pip install esptool + pio run -t buildfs + pio run - name: Merge firmware and SPIFFS run: | @@ -48,20 +53,7 @@ jobs: 0x290000 .pio/build/esp32dev/spiffs.bin - name: Prepare OTA firmware - run: | - cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/filaman_ota.bin - - - name: Get version from tag - id: get_version - run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT - - - name: Read CHANGELOG.md - id: changelog - run: | - CHANGELOG=$(awk "/## \\[${{ steps.get_version.outputs.VERSION }}\\]/{p=1;print;next} /## \\[/{p=0} p" CHANGELOG.md) - echo "CHANGES<> $GITHUB_OUTPUT - echo "$CHANGELOG" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT + run: cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/filaman_ota.bin - name: Create Release env: @@ -69,33 +61,54 @@ jobs: GITEA_API_URL: ${{ secrets.GITEA_API_URL }} GITEA_REPOSITORY: ${{ secrets.GITEA_REPOSITORY }} run: | - # Create release using Gitea API - RESPONSE=$(curl -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - -H "accept: application/json" \ - "${GITEA_API_URL}/repos/${GITEA_REPOSITORY}/releases" \ - -d '{ - "tag_name": "${{ github.ref_name }}", - "name": "Release ${{ steps.get_version.outputs.VERSION }}", - "body": "${{ steps.changelog.outputs.CHANGES }}", - "draft": false, - "prerelease": false - }') + # Validate and sanitize API URL + if [[ ! "$GITEA_API_URL" =~ ^https?:// ]]; then + echo "Error: GITEA_API_URL must start with http:// or https://" + exit 1 + fi - # Extract release ID from response - RELEASE_ID=$(echo $RESPONSE | jq -r .id) + # Remove trailing slash and ensure /api/v1 + GITEA_API_URL="${GITEA_API_URL%/}" + if [[ ! "$GITEA_API_URL" =~ /api/v1$ ]]; then + GITEA_API_URL="${GITEA_API_URL}/api/v1" + fi - # Upload full firmware - curl -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/octet-stream" \ - "${GITEA_API_URL}/repos/${GITEA_REPOSITORY}/releases/${RELEASE_ID}/assets?name=filaman_full.bin" \ - --data-binary @.pio/build/esp32dev/filaman_full.bin + echo "Creating Gitea release..." + RESPONSE=$(curl -sS -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + "${GITEA_API_URL}/repos/${GITEA_REPOSITORY}/releases" \ + -d @- << EOF +{ + "tag_name": "${{ github.ref_name }}", + "name": "Release ${{ inputs.version }}", + "body": ${{ toJSON(inputs.changelog) }}, + "draft": false, + "prerelease": false +} +EOF +) - # Upload OTA firmware - curl -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/octet-stream" \ - "${GITEA_API_URL}/repos/${GITEA_REPOSITORY}/releases/${RELEASE_ID}/assets?name=filaman_ota.bin" \ - --data-binary @.pio/build/esp32dev/filaman_ota.bin \ No newline at end of file + # Extract and validate release ID + RELEASE_ID=$(echo "$RESPONSE" | jq -r .id) + if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then + echo "Error: Failed to get release ID" + echo "API Response:" + echo "$RESPONSE" | jq . + exit 1 + fi + + # Upload binary files + for file in "filaman_full.bin" "filaman_ota.bin"; do + echo "Uploading $file..." + if ! curl -sS -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/octet-stream" \ + "${GITEA_API_URL}/repos/${GITEA_REPOSITORY}/releases/${RELEASE_ID}/assets?name=${file}" \ + --data-binary "@.pio/build/esp32dev/${file}"; then + echo "Error: Failed to upload $file" + exit 1 + fi + echo "Successfully uploaded $file" + done \ No newline at end of file diff --git a/.github/workflows/providers/github-release.yml b/.github/workflows/providers/github-release.yml index d86a694..ab45415 100644 --- a/.github/workflows/providers/github-release.yml +++ b/.github/workflows/providers/github-release.yml @@ -1,7 +1,14 @@ name: GitHub Release on: - workflow_call: # This workflow will only be triggered when called by another workflow + workflow_call: + inputs: + version: + required: true + type: string + changelog: + required: true + type: string permissions: contents: write # Required for creating releases @@ -21,20 +28,16 @@ jobs: with: python-version: '3.x' - - name: Install PlatformIO + - name: Install dependencies run: | python -m pip install --upgrade pip - pip install --upgrade platformio + pip install --upgrade platformio esptool - name: Build Firmware run: | pio run -t buildfs # Build SPIFFS pio run # Build firmware - - name: Install esptool - run: | - pip install esptool - - name: Merge firmware and SPIFFS run: | esptool.py --chip esp32 merge_bin \ @@ -48,36 +51,14 @@ jobs: 0x290000 .pio/build/esp32dev/spiffs.bin - name: Prepare OTA firmware - run: | - # Use PlatformIO to create a proper OTA image - cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/filaman_ota.bin + run: cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/filaman_ota.bin - - name: Get version from tag - id: get_version - run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT - - - name: Read CHANGELOG.md - id: changelog - run: | - CHANGELOG=$(awk "/## \\[${{ steps.get_version.outputs.VERSION }}\\]/{p=1;print;next} /## \\[/{p=0} p" CHANGELOG.md) - echo "CHANGES<> $GITHUB_OUTPUT - echo "$CHANGELOG" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Install and Configure GitHub CLI - run: | - curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ - && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ - && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ - && sudo apt update \ - && sudo apt install gh -y - - - name: Create Release with GitHub CLI + - name: Create Release env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh release create "${{ github.ref_name }}" \ - --title "Release ${{ steps.get_version.outputs.VERSION }}" \ - --notes "${{ steps.changelog.outputs.CHANGES }}" \ + --title "Release ${{ inputs.version }}" \ + --notes "${{ inputs.changelog }}" \ ".pio/build/esp32dev/filaman_full.bin#filaman_full.bin" \ ".pio/build/esp32dev/filaman_ota.bin#filaman_ota.bin" \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f9017d7..2fc20a3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,136 +6,41 @@ on: - 'v*' jobs: - release: + prepare: runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.VERSION }} + changelog: ${{ steps.changelog.outputs.CHANGES }} + provider: ${{ steps.detect-provider.outputs.provider }} steps: - uses: actions/checkout@v4 - - name: Verify Gitea API Connection - if: github.server_url != 'https://github.com' - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - GITEA_API_URL: ${{ secrets.GITEA_API_URL }} + - name: Detect provider + id: detect-provider run: | - # Sanitize URL - GITEA_BASE_URL=$(echo "$GITEA_API_URL" | sed 's#/\+$##' | sed 's#/api/v1$##') - GITEA_API_ENDPOINT="${GITEA_BASE_URL}/api/v1" - - echo "Testing connection to Gitea API..." - echo "API Endpoint: ${GITEA_API_ENDPOINT}" - - # Try to get Gitea version - RESPONSE=$(curl -sSf -w "\nHTTP_STATUS:%{http_code}" \ - -H "Authorization: token ${GITEA_TOKEN}" \ - "${GITEA_API_ENDPOINT}/version") - - HTTP_STATUS=$(echo "$RESPONSE" | grep "HTTP_STATUS:" | cut -d":" -f2) - API_RESPONSE=$(echo "$RESPONSE" | grep -v "HTTP_STATUS:") - - echo "HTTP Status: ${HTTP_STATUS}" - echo "API Response: ${API_RESPONSE}" - - if [ "$HTTP_STATUS" != "200" ]; then - echo "Error: Could not connect to Gitea API" - exit 1 + if [[ "$GITHUB_SERVER_URL" == "https://github.com" ]]; then + echo "provider=github" >> $GITHUB_OUTPUT + else + echo "provider=gitea" >> $GITHUB_OUTPUT fi - - echo "Gitea API connection successful" - - - name: Parse and validate Gitea URL - if: github.server_url != 'https://github.com' - env: - GITEA_API_URL: ${{ secrets.GITEA_API_URL }} - run: | - validate_url() { - local url="$1" - # Check if URL starts with protocol - if [[ ! "$url" =~ ^https?:// ]]; then - echo "Error: URL must start with http:// or https://" - return 1 - fi - - # Extract host part - local host=$(echo "$url" | sed -E 's#^https?://##' | cut -d'/' -f1) - if [ -z "$host" ]; then - echo "Error: No host found in URL" - return 1 - fi - - # Validate host format (domain or IP) - if [[ ! "$host" =~ ^[a-zA-Z0-9.-]+$ ]]; then - echo "Error: Invalid host format" - return 1 - fi - - echo "URL validation passed" - return 0 - } - - echo "Validating Gitea API URL: $GITEA_API_URL" - if ! validate_url "$GITEA_API_URL"; then - exit 1 - fi - - # Store validated base URL for later use - GITEA_BASE_URL=$(echo "$GITEA_API_URL" | sed 's#/\+$##' | sed 's#/api/v1$##') - echo "GITEA_BASE_URL=$GITEA_BASE_URL" >> $GITHUB_ENV - - # Test URL resolution - echo "Testing DNS resolution..." - host=$(echo "$GITEA_BASE_URL" | sed -E 's#^https?://##' | cut -d'/' -f1) - if ! ping -c 1 "$host" > /dev/null 2>&1; then - echo "Warning: Could not ping host (this might be normal if ICMP is blocked)" - fi - - # Test HTTPS connection - echo "Testing HTTPS connection..." - if ! curl -sSf -o /dev/null "$GITEA_BASE_URL"; then - echo "Error: Could not establish HTTPS connection to $GITEA_BASE_URL" - exit 1 - fi - - echo "URL validation and connection test passed" - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: Install PlatformIO - run: | - python -m pip install --upgrade pip - pip install --upgrade platformio - - - name: Build Firmware - run: | - pio run -t buildfs # Build SPIFFS - pio run # Build firmware - - - name: Install esptool - run: | - pip install esptool - - - name: Merge firmware and SPIFFS - run: | - esptool.py --chip esp32 merge_bin \ - --flash_mode dio \ - --flash_freq 40m \ - --flash_size 4MB \ - -o .pio/build/esp32dev/filaman_full.bin \ - 0x1000 .pio/build/esp32dev/bootloader.bin \ - 0x8000 .pio/build/esp32dev/partitions.bin \ - 0x10000 .pio/build/esp32dev/firmware.bin \ - 0x290000 .pio/build/esp32dev/spiffs.bin - - - name: Prepare OTA firmware - run: | - cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/filaman_ota.bin - name: Get version from tag id: get_version run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT + - name: Verify version match + run: | + PIO_VERSION=$(grep '^version = ' platformio.ini | cut -d'"' -f2) + TAG_VERSION=${{ steps.get_version.outputs.VERSION }} + + echo "PlatformIO version: $PIO_VERSION" + echo "Tag version: $TAG_VERSION" + + if [ "$PIO_VERSION" != "$TAG_VERSION" ]; then + echo "Error: Version mismatch between tag ($TAG_VERSION) and platformio.ini ($PIO_VERSION)" + exit 1 + fi + - name: Read CHANGELOG.md id: changelog run: | @@ -144,182 +49,20 @@ jobs: echo "$CHANGELOG" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - - name: Install jq - if: ${{ github.server_url != 'https://github.com' }} - run: sudo apt-get install -y jq + github-release: + needs: prepare + if: needs.prepare.outputs.provider == 'github' + uses: ./.github/workflows/providers/github-release.yml + with: + version: ${{ needs.prepare.outputs.version }} + changelog: ${{ needs.prepare.outputs.changelog }} + secrets: inherit - - name: Debug Environment Variables - run: | - echo "GITHUB_SERVER_URL: $GITHUB_SERVER_URL" - if [ -n "$GITEA_TOKEN" ]; then - echo "GITEA_TOKEN is set" - else - echo "GITEA_TOKEN is not set" - fi - if [ -n "${{ secrets.GITEA_API_URL }}" ]; then - echo "GITEA_API_URL from secrets: ${{ secrets.GITEA_API_URL }}" - else - echo "GITEA_API_URL is not set in secrets" - fi - if [ -n "${{ secrets.GITEA_REPOSITORY }}" ]; then - echo "GITEA_REPOSITORY from secrets: ${{ secrets.GITEA_REPOSITORY }}" - else - echo "GITEA_REPOSITORY is not set in secrets" - fi - - - name: Validate Gitea Configuration - if: github.server_url != 'https://github.com' - run: | - if [ -z "${{ secrets.GITEA_API_URL }}" ]; then - echo "::error::GITEA_API_URL is not configured in repository secrets" - exit 1 - fi - - if [ -z "${{ secrets.GITEA_TOKEN }}" ]; then - echo "::error::GITEA_TOKEN is not configured in repository secrets" - exit 1 - fi - - if [ -z "${{ secrets.GITEA_REPOSITORY }}" ]; then - echo "::error::GITEA_REPOSITORY is not configured in repository secrets" - exit 1 - fi - - # Validate URL format - if [[ ! "${{ secrets.GITEA_API_URL }}" =~ ^https?:// ]]; then - echo "::error::GITEA_API_URL must start with http:// or https://" - exit 1 - fi - - echo "Gitea configuration is valid" - - - name: Determine and run release process - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - GITEA_API_URL: ${{ secrets.GITEA_API_URL }} - GITEA_REPOSITORY: ${{ secrets.GITEA_REPOSITORY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - if [[ "$GITHUB_SERVER_URL" == "https://github.com" ]]; then - echo "Creating GitHub Release..." - curl -X POST \ - -H "Authorization: token ${GITHUB_TOKEN}" \ - -H "Accept: application/vnd.github.v3+json" \ - https://api.github.com/repos/${{ github.repository }}/releases \ - -d '{ - "tag_name": "${{ github.ref_name }}", - "name": "Release ${{ steps.get_version.outputs.VERSION }}", - "body": "${{ steps.changelog.outputs.CHANGES }}", - "draft": false, - "prerelease": false - }' > release.json - - UPLOAD_URL=$(jq -r .upload_url release.json | sed 's/{?name,label}//') - - # Upload full firmware - curl -X POST \ - -H "Authorization: token ${GITHUB_TOKEN}" \ - -H "Content-Type: application/octet-stream" \ - "${UPLOAD_URL}?name=filaman_full.bin" \ - --data-binary @.pio/build/esp32dev/filaman_full.bin - - # Upload OTA firmware - curl -X POST \ - -H "Authorization: token ${GITHUB_TOKEN}" \ - -H "Content-Type: application/octet-stream" \ - "${UPLOAD_URL}?name=filaman_ota.bin" \ - --data-binary @.pio/build/esp32dev/filaman_ota.bin - else - echo "Creating Gitea Release..." - - # Validate and sanitize inputs - if [ -z "$GITEA_TOKEN" ] || [ -z "$GITEA_API_URL" ] || [ -z "$GITEA_REPOSITORY" ]; then - echo "Error: Missing required Gitea configuration" - exit 1 - fi - - # Remove trailing slash and /api/v1 if present - GITEA_BASE_URL=$(echo "$GITEA_API_URL" | sed 's#/\+$##' | sed 's#/api/v1$##') - - # Construct proper API URL - GITEA_API_ENDPOINT="${GITEA_BASE_URL}/api/v1" - - echo "Debug: URL Components" - echo "GITEA_BASE_URL: ${GITEA_BASE_URL}" - echo "GITEA_API_ENDPOINT: ${GITEA_API_ENDPOINT}" - echo "GITEA_REPOSITORY: ${GITEA_REPOSITORY}" - - # Test API connection with verbose output - echo "Testing API connection..." - curl -v "${GITEA_API_ENDPOINT}/version" 2>&1 | tee api_test.log - if [ ${PIPESTATUS[0]} -ne 0 ]; then - echo "Error: Could not connect to Gitea API" - echo "API Test Log:" - cat api_test.log - exit 1 - fi - - # Prepare release data - RELEASE_DATA=$(cat << EOF -{ - "tag_name": "${{ github.ref_name }}", - "name": "Release ${{ steps.get_version.outputs.VERSION }}", - "body": $(echo "${{ steps.changelog.outputs.CHANGES }}" | jq -R -s .), - "draft": false, - "prerelease": false -} -EOF -) - - echo "Debug: Release Payload" - echo "$RELEASE_DATA" | jq . - - # Create release with full debug output - echo "Creating release at ${GITEA_API_ENDPOINT}/repos/${GITEA_REPOSITORY}/releases" - RESPONSE=$(curl -v -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - -H "Accept: application/json" \ - "${GITEA_API_ENDPOINT}/repos/${GITEA_REPOSITORY}/releases" \ - -d "$RELEASE_DATA" 2>&1 | tee release_creation.log) - - if [ ${PIPESTATUS[0]} -ne 0 ]; then - echo "Error: Failed to create release" - echo "Release Creation Log:" - cat release_creation.log - exit 1 - fi - - # Extract and validate release ID - RELEASE_ID=$(echo "$RESPONSE" | jq -r .id) - if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then - echo "Error: Failed to get release ID" - echo "API Response:" - echo "$RESPONSE" | jq . - echo "Full Response Log:" - cat release_creation.log - exit 1 - fi - - # Upload assets with debug output - for asset in "filaman_full.bin" "filaman_ota.bin"; do - echo "Uploading ${asset}..." - ASSET_URL="${GITEA_API_ENDPOINT}/repos/${GITEA_REPOSITORY}/releases/${RELEASE_ID}/assets?name=${asset}" - echo "Debug: Uploading to ${ASSET_URL}" - - curl -v -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/octet-stream" \ - "${ASSET_URL}" \ - --data-binary "@.pio/build/esp32dev/${asset}" 2>&1 | tee "upload_${asset}.log" - - if [ ${PIPESTATUS[0]} -ne 0 ]; then - echo "Error: Failed to upload ${asset}" - echo "Upload Log:" - cat "upload_${asset}.log" - exit 1 - fi - done - - echo "Release process completed successfully" - fi \ No newline at end of file + gitea-release: + needs: prepare + if: needs.prepare.outputs.provider == 'gitea' + uses: ./.github/workflows/providers/gitea-release.yml + with: + version: ${{ needs.prepare.outputs.version }} + changelog: ${{ needs.prepare.outputs.changelog }} + secrets: inherit \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 36c51a4..3344a5f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.2.10" +version = "1.2.11" [env:esp32dev] platform = espressif32