Compile #18
This file contains 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: Compile | |
on: | |
workflow_dispatch: | |
inputs: | |
buildType: | |
description: "Select the build type" | |
required: true | |
type: choice | |
options: | |
- "prerelease" | |
- "all" | |
default: "prerelease" | |
jobs: | |
build: | |
name: Build for ${{ matrix.target.name }} | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
target: | |
- { name: "esp32-generic", idf_target: "esp32", sdkconfig_file: "configs/sdkconfig.default.esp32", zip_name: "esp32-generic.zip" } | |
- { name: "esp32s2-generic", idf_target: "esp32s2", sdkconfig_file: "configs/sdkconfig.default.esp32s2", zip_name: "esp32s2-generic.zip"} | |
- { name: "esp32s3-generic", idf_target: "esp32s3", sdkconfig_file: "configs/sdkconfig.default.esp32s3", zip_name: "esp32s3-generic.zip" } | |
- { name: "esp32c3-generic", idf_target: "esp32c3", sdkconfig_file: "configs/sdkconfig.default.esp32c3", zip_name: "esp32c3-generic.zip" } | |
- { name: "esp32c6-generic", idf_target: "esp32c6", sdkconfig_file: "configs/sdkconfig.default.esp32c6", zip_name: "esp32c6-generic.zip" } | |
- { name: "Awok V5", idf_target: "esp32s2", sdkconfig_file: "configs/sdkconfig.default.esp32s2", zip_name: "esp32v5_awok.zip"} | |
# Dev Kit configurations (LED on, no screen support) | |
- { name: "esp32c3-devkit", idf_target: "esp32c3", sdkconfig_file: "configs/sdkconfig.devkit.esp32c3", zip_name: "esp32c3-devkit.zip"} | |
- { name: "esp32c6-devkit", idf_target: "esp32c6", sdkconfig_file: "configs/sdkconfig.devkit.esp32c6", zip_name: "esp32c6-devkit.zip"} | |
# Ghost board (LED on, special pin and LED count) | |
- { name: "ghostboard", idf_target: "esp32c6", sdkconfig_file: "configs/sdkconfig.ghostboard", zip_name: "ghostboard.zip"} | |
# Screen-supported builds | |
- { name: "MarauderV4_FlipperHub", idf_target: "esp32", sdkconfig_file: "configs/sdkconfig.marauderv4", zip_name: "MarauderV4_FlipperHub.zip"} | |
- { name: "MarauderV6&AwokDual", idf_target: "esp32", sdkconfig_file: "configs/sdkconfig.marauderv6", zip_name: "MarauderV6_AwokDual.zip"} | |
- { name: "AwokMini", idf_target: "esp32", sdkconfig_file: "configs/sdkconfig.awokmini", zip_name: "AwokMini.zip"} | |
- { name: "ESP32-S3-Cardputer", idf_target: "esp32s3", sdkconfig_file: "configs/sdkconfig.cardputer", zip_name: "ESP32-S3-Cardputer.zip"} | |
#- { name: "LillyGoTWatch_S3", idf_target: "esp32s3", sdkconfig_file: "configs/sdkconfig.S3TWatch", zip_name: "lillygos3watch.zip"} | |
# CYD (Cheap Yellow Display) with touch screen | |
- { name: "CYD2USB", idf_target: "esp32", sdkconfig_file: "configs/sdkconfig.CYD2USB", zip_name: "CYD2USB.zip"} | |
- { name: "CYDMicroUSB", idf_target: "esp32", sdkconfig_file: "configs/sdkconfig.CYDMicroUSB", zip_name: "CYDMicroUSB.zip"} | |
- { name: "CYDDualUSB", idf_target: "esp32", sdkconfig_file: "configs/sdkconfig.CYDDualUSB", zip_name: "CYDDualUSB.zip"} | |
- { name: "CYD2USB2.4_Inch", idf_target: "esp32", sdkconfig_file: "configs/sdkconfig.CYD2USB2.4Inch", zip_name: "CYD2USB2.4Inch.zip"} | |
- { name: "CYD2USB2.4_Inch_C", idf_target: "esp32", sdkconfig_file: "configs/sdkconfig.CYD2USB2.4Inch_C_Varient", zip_name: "CYD2USB2.4Inch_C.zip"} | |
# 7-inch boards | |
- { name: "Waveshare_LCD", idf_target: "esp32s3", sdkconfig_file: "configs/sdkconfig.waveshare7inch", zip_name: "Waveshare_LCD.zip"} | |
- { name: "Crowtech_LCD", idf_target: "esp32s3", sdkconfig_file: "configs/sdkconfig.crowtech7inch", zip_name: "Crowtech_LCD.zip"} | |
steps: | |
- name: Check Out Repository | |
uses: actions/checkout@v3 | |
- name: Set up Python | |
uses: actions/setup-python@v4 | |
with: | |
python-version: '3.9' | |
- name: Install ESP-IDF | |
run: | | |
sudo apt-get update | |
sudo apt-get install -y wget git flex bison gperf python3-pip python3-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util | |
git clone -b v5.3.1 --depth 1 https://github.com/espressif/esp-idf.git ~/esp-idf | |
~/esp-idf/install.sh | |
- name: Apply Custom SDK Config | |
run: | | |
cp "${{ matrix.target.sdkconfig_file }}" sdkconfig.defaults | |
- name: Set up ESP-IDF and Target | |
run: | | |
. ~/esp-idf/export.sh | |
export IDF_TARGET=${{ matrix.target.idf_target }} | |
echo "IDF_TARGET=${{ matrix.target.idf_target }}" >> $GITHUB_ENV | |
- name: Clean and Build Project | |
env: | |
SDKCONFIG_DEFAULTS: "sdkconfig.defaults" | |
run: | | |
. ~/esp-idf/export.sh | |
idf.py clean | |
idf.py build | |
- name: Download Bootloader | |
run: | | |
BOOTLOADER_URL="https://cdn.spookytools.com/bootloaders/${{ matrix.target.idf_target }}.bin" | |
BOOTLOADER_PATH="build/bootloader.bin" | |
echo "Downloading bootloader from $BOOTLOADER_URL..." | |
curl -L -o "$BOOTLOADER_PATH" "$BOOTLOADER_URL" | |
if [ ! -f "$BOOTLOADER_PATH" ]; then | |
echo "Error: Bootloader could not be downloaded." | |
exit 1 | |
else | |
echo "Bootloader downloaded successfully." | |
fi | |
- name: Package Artifacts into ZIP | |
run: | | |
ARTIFACT_DIR="packaged_artifacts" | |
ZIP_FILE="${{ matrix.target.zip_name }}" | |
mkdir -p "$ARTIFACT_DIR" | |
cp build/partition_table/partition-table.bin "$ARTIFACT_DIR/" | |
cp build/*.bin "$ARTIFACT_DIR/" | |
echo "Packaging into zip: $ZIP_FILE" | |
cd "$ARTIFACT_DIR" | |
zip "../$ZIP_FILE" ./* | |
cd .. | |
echo "Zip file $ZIP_FILE created." | |
ls -lh "$ZIP_FILE" | |
- name: Upload Build Artifacts to GitHub | |
uses: actions/upload-artifact@v3 | |
with: | |
name: ${{ matrix.target.zip_name }} | |
path: ${{ matrix.target.zip_name }} | |
# --------------------------------------------------------------- | |
# This job uploads all artifacts to the correct R2 path | |
# AND optionally does the "prerelease" extras (boards.json, | |
# Discord commit history, etc.) if buildType == 'prerelease'. | |
# --------------------------------------------------------------- | |
upload_all: | |
name: Upload Artifacts | |
needs: build | |
runs-on: ubuntu-latest | |
steps: | |
- name: Check Out Repository | |
uses: actions/checkout@v3 | |
with: | |
fetch-depth: 0 # so we can get commit logs, etc. | |
- name: Download All Artifacts | |
uses: actions/download-artifact@v3 | |
with: | |
path: all_artifacts | |
- name: Verify and Flatten Artifacts | |
run: | | |
echo "Checking and flattening artifacts..." | |
mkdir -p flat_artifacts | |
if [ -d "all_artifacts" ] && [ "$(ls -A all_artifacts)" ]; then | |
find all_artifacts -type f -exec cp {} flat_artifacts/ \; | |
echo "Flattened artifacts:" | |
ls -lh flat_artifacts | |
else | |
echo "No artifacts found or directory is empty." | |
exit 1 | |
fi | |
- name: Determine R2 Path (Set ENV) | |
run: | | |
if [ "${{ github.event.inputs.buildType }}" = "prerelease" ]; then | |
echo "R2_PATH=GhostESPBins/prerelease" >> $GITHUB_ENV | |
else | |
echo "R2_PATH=GhostESPBins" >> $GITHUB_ENV | |
fi | |
- name: Install rclone | |
run: | | |
curl -fsSL https://rclone.org/install.sh | sudo bash | |
- name: Configure rclone for Cloudflare R2 | |
env: | |
R2_ACCESS_KEY: ${{ secrets.R2_ACCESS_KEY }} | |
R2_SECRET_KEY: ${{ secrets.R2_SECRET_KEY }} | |
run: | | |
mkdir -p ~/.config/rclone | |
cat <<EOF > ~/.config/rclone/rclone.conf | |
[cloudflare_r2] | |
type = s3 | |
provider = Cloudflare | |
access_key_id = $R2_ACCESS_KEY | |
secret_access_key = $R2_SECRET_KEY | |
endpoint = https://fb5f7d31bedfe4f3538ddfa6db491962.r2.cloudflarestorage.com | |
EOF | |
- name: Upload All Artifacts to Cloudflare R2 | |
env: | |
R2_BUCKET: "spooksapi" | |
R2_PATH: ${{ env.R2_PATH }} | |
run: | | |
echo "Uploading artifacts to Cloudflare R2 -> $R2_PATH" | |
for file in flat_artifacts/*; do | |
if [ -f "$file" ]; then | |
echo "Uploading $file..." | |
rclone copy "$file" "cloudflare_r2:${R2_BUCKET}/${R2_PATH}" --progress --s3-no-check-bucket | |
else | |
echo "Skipping $file as it is not a valid file." | |
fi | |
done | |
echo "All artifacts uploaded successfully." | |
- name: Get the Latest Release ID (Including Pre-releases) | |
id: get_release | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
latest_release=$(curl -s \ | |
-H "Authorization: token $GITHUB_TOKEN" \ | |
-H "Accept: application/vnd.github.v3+json" \ | |
"https://api.github.com/repos/${{ github.repository }}/releases" | jq '[.[] | select(.draft == false)] | .[0]') | |
release_id=$(echo "$latest_release" | jq -r '.id') | |
echo "Latest release ID (including pre-releases) is $release_id" | |
echo "::set-output name=release_id::$release_id" | |
- name: Upload Artifacts to Latest Release | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
for file in flat_artifacts/*; do | |
if [ -f "$file" ] && [ -s "$file" ]; then | |
echo "Uploading $file to GitHub Release..." | |
curl -X POST \ | |
-H "Authorization: token $GITHUB_TOKEN" \ | |
-H "Content-Type: application/zip" \ | |
--data-binary @"$file" \ | |
"https://uploads.github.com/repos/${{ github.repository }}/releases/${{ steps.get_release.outputs.release_id }}/assets?name=$(basename $file)" | |
else | |
echo "Skipping $file as it is either empty or not a valid file." | |
fi | |
done | |
# ------------------ | |
# If = 'all' path | |
# ------------------ | |
- name: Notify Discord of Successful Upload (ALL) | |
if: ${{ github.event.inputs.buildType == 'all' }} | |
env: | |
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} | |
run: | | |
payload=$(cat <<EOF | |
{ | |
"embeds": [ | |
{ | |
"title": "🎉 New Build Artifacts Uploaded!", | |
"description": "All build artifacts have been successfully uploaded to Cloudflare R2 and GitHub Release.", | |
"color": 5814783, | |
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" | |
} | |
] | |
} | |
EOF | |
) | |
curl -X POST \ | |
-H "Content-Type: application/json" \ | |
-d "$payload" \ | |
"$DISCORD_WEBHOOK_URL" | |
# ---------------------- | |
# If = 'prerelease' path | |
# ---------------------- | |
- name: Get Commit History | |
if: ${{ github.event.inputs.buildType == 'prerelease' }} | |
id: get_commits | |
run: | | |
# Get the last 10 commits | |
commits=$(git log --pretty=format:"- %s" -n 10) | |
# Escape newlines and quotes for JSON | |
commits="${commits//'%'/'%25'}" | |
commits="${commits//$'\n'/'\\n'}" | |
commits="${commits//$'\r'/'%0D'}" | |
commits="${commits//'"'/'\"'}" | |
echo "commits=$commits" >> $GITHUB_OUTPUT | |
- name: Notify Discord of Successful Upload (PRERELEASE) | |
if: ${{ github.event.inputs.buildType == 'prerelease' }} | |
env: | |
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} | |
run: | | |
BUILD_DATE=$(date -u +"%Y-%m-%d") | |
BUILD_VERSION=$(date -u +"%Y%m%d") | |
payload=$(cat <<EOF | |
{ | |
"embeds": [ | |
{ | |
"title": "🚀 GhostESP Prerelease Build - $BUILD_DATE", | |
"description": "A new prerelease build has been uploaded to Cloudflare R2 and GitHub Release.\\n\\n**Version:** Pre-$BUILD_VERSION\\n\\n**Changes since last prerelease:**\\n${{ steps.get_commits.outputs.commits }}\\n\\n**Flash your device:**\\n🔗 [Flash using GhostESP Web Flasher](https://flasher.ghostesp.net)", | |
"color": 16750848, | |
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")", | |
"footer": { | |
"text": "GhostESP Prerelease Build $BUILD_VERSION" | |
} | |
} | |
] | |
} | |
EOF | |
) | |
curl -X POST \ | |
-H "Content-Type: application/json" \ | |
-d "$payload" \ | |
"$DISCORD_WEBHOOK_URL" | |
- name: Generate boards.json | |
if: ${{ github.event.inputs.buildType == 'prerelease' }} | |
run: | | |
cat > boards.json << 'EOF' | |
{ | |
"boards": { | |
"ESP32": { | |
"generic": { | |
"name": "ESP32 Generic", | |
"zip_file": "esp32-generic.zip", | |
"chip_type": "ESP32" | |
}, | |
"marauderv4": { | |
"name": "MarauderV4 FlipperHub", | |
"zip_file": "MarauderV4_FlipperHub.zip", | |
"chip_type": "ESP32" | |
}, | |
"marauderv6": { | |
"name": "MarauderV6 & AwokDual", | |
"zip_file": "MarauderV6_AwokDual.zip", | |
"chip_type": "ESP32" | |
}, | |
"awokmini": { | |
"name": "AwokMini", | |
"zip_file": "AwokMini.zip", | |
"chip_type": "ESP32" | |
}, | |
"cyd2usb": { | |
"name": "CYD2USB", | |
"zip_file": "CYD2USB.zip", | |
"chip_type": "ESP32" | |
}, | |
"cydmicrousb": { | |
"name": "CYDMicroUSB", | |
"zip_file": "CYDMicroUSB.zip", | |
"chip_type": "ESP32" | |
}, | |
"cyddualusb": { | |
"name": "CYDDualUSB", | |
"zip_file": "CYDDualUSB.zip", | |
"chip_type": "ESP32" | |
}, | |
"cyd2usb24inch": { | |
"name": "CYD2USB 2.4 Inch", | |
"zip_file": "CYD2USB2.4Inch.zip", | |
"chip_type": "ESP32" | |
} | |
}, | |
"ESP32S2": { | |
"generic": { | |
"name": "ESP32-S2 Generic", | |
"zip_file": "esp32s2-generic.zip", | |
"chip_type": "ESP32-S2" | |
}, | |
"awokv5": { | |
"name": "Awok V5", | |
"zip_file": "esp32v5_awok.zip", | |
"chip_type": "ESP32-S2" | |
} | |
}, | |
"ESP32S3": { | |
"generic": { | |
"name": "ESP32-S3 Generic", | |
"zip_file": "esp32s3-generic.zip", | |
"chip_type": "ESP32-S3" | |
}, | |
"cardputer": { | |
"name": "ESP32-S3-Cardputer", | |
"zip_file": "ESP32-S3-Cardputer.zip", | |
"chip_type": "ESP32-S3" | |
}, | |
"waveshare": { | |
"name": "Waveshare LCD", | |
"zip_file": "Waveshare_LCD.zip", | |
"chip_type": "ESP32-S3" | |
}, | |
"crowtech": { | |
"name": "Crowtech LCD", | |
"zip_file": "Crowtech_LCD.zip", | |
"chip_type": "ESP32-S3" | |
} | |
}, | |
"ESP32C3": { | |
"generic": { | |
"name": "ESP32-C3 Generic", | |
"zip_file": "esp32c3-generic.zip", | |
"chip_type": "ESP32-C3" | |
}, | |
"devkit": { | |
"name": "ESP32-C3 DevKit", | |
"zip_file": "esp32c3-devkit.zip", | |
"chip_type": "ESP32-C3" | |
} | |
}, | |
"ESP32C6": { | |
"generic": { | |
"name": "ESP32-C6 Generic", | |
"zip_file": "esp32c6-generic.zip", | |
"chip_type": "ESP32-C6" | |
}, | |
"devkit": { | |
"name": "ESP32-C6 DevKit", | |
"zip_file": "esp32c6-devkit.zip", | |
"chip_type": "ESP32-C6" | |
}, | |
"ghostboard": { | |
"name": "GhostBoard", | |
"zip_file": "ghostboard.zip", | |
"chip_type": "ESP32-C6" | |
} | |
} | |
}, | |
"version": "${{ github.sha }}", | |
"build_date": "$(date -u +"%Y-%m-%d")", | |
"build_number": "$(date -u +"%Y%m%d")" | |
} | |
EOF | |
echo "Generated boards.json with target information" | |
- name: Upload boards.json to Cloudflare R2 | |
if: ${{ github.event.inputs.buildType == 'prerelease' }} | |
env: | |
R2_BUCKET: "spooksapi" | |
R2_PATH: ${{ env.R2_PATH }} | |
run: | | |
echo "Uploading boards.json to Cloudflare R2 ($R2_PATH)..." | |
rclone copy "boards.json" "cloudflare_r2:${R2_BUCKET}/${R2_PATH}" --progress --s3-no-check-bucket |