CustoPiZe #66
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: "CustoPiZe" | |
on: | |
repository_dispatch: | |
types: [octopi_release, octoprint_release] | |
workflow_dispatch: | |
inputs: | |
octopi_version: | |
description: "OctoPi version (leave empty to use latest stable release)" | |
required: false | |
default: '' | |
octoprint_version: | |
description: "OctoPrint version (leave empty to use latest stable release)" | |
required: false | |
default: '' | |
jobs: | |
build: | |
name: "Build" | |
runs-on: ubuntu-latest | |
outputs: | |
octoprint-version: ${{ env.OCTOPRINT_VERSION }} | |
octopi-version: ${{ env.OCTOPI_VERSION }} | |
tag: ${{ env.RELEASE_TAG }} | |
image-zip: ${{ env.IMAGE_ZIP }} | |
image-url: ${{ env.IMAGE_URL }} | |
steps: | |
- name: "⬇ Checkout" | |
uses: actions/checkout@v4 | |
- name: "🔎 Determine OctoPi version" | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
let release = null; | |
let version = ''; | |
if (context.eventName === "respository_dispatch" && context.action === "octopi_release") { | |
version = context.payload.client_payload.version; | |
console.log(`Version from repository dispatch: ${version}`); | |
} else if (context.eventName === "workflow_dispatch") { | |
version = context.payload.inputs.octopi_version; | |
console.log(`Version from workflow dispatch: ${version}`); | |
} | |
if (version) { | |
console.log(`Fetching release of ${version}`); | |
const query = `query { | |
repository(owner: "guysoft", name: "Octopi") { | |
release(tagName:"${version}") { | |
tagName | |
releaseAssets(first:5) { | |
nodes { | |
name | |
downloadUrl | |
} | |
} | |
} | |
} | |
}`; | |
const result = await github.graphql(query); | |
console.log({result}); | |
release = result.repository.release; | |
} else { | |
console.log("Fetching latest release"); | |
const query = `query { | |
repository(owner:"guysoft", name:"OctoPi") { | |
latestRelease { | |
tagName | |
releaseAssets(first:5) { | |
nodes { | |
name | |
downloadUrl | |
} | |
} | |
} | |
} | |
}`; | |
const result = await github.graphql(query); | |
console.log({result}); | |
release = result.repository.latestRelease; | |
} | |
if (!release || !release.tagName || !release.releaseAssets || !release.releaseAssets.nodes) core.setFailed("Could not find OctoPi release"); | |
const octopiVersion = release.tagName; | |
let octopiUrl = null; | |
for (const asset of release.releaseAssets.nodes) { | |
if (asset.name.startsWith("octopi-") && asset.name.includes("-armhf-") && asset.name.endsWith(".zip")) { | |
octopiUrl = asset.downloadUrl; | |
break; | |
} | |
} | |
if (!octopiUrl) core.setFailed("Could not find OctoPi download URL"); | |
console.log(`OctoPi version: ${octopiVersion}`) | |
console.log(`OctoPi download URL: ${octopiUrl}`) | |
core.exportVariable("OCTOPI_VERSION", octopiVersion) | |
core.exportVariable("OCTOPI_URL", octopiUrl) | |
- name: "🔎 Determine OctoPrint version" | |
run: | | |
if [[ "${{ github.event_name }}" = "repository_dispatch" && "${{ github.event.action }}" = "octoprint_release" ]]; then | |
OCTOPRINT_VERSION="${{ github.event.client_payload.version }}" | |
echo "Version from repository dispatch: $OCTOPRINT_VERSION" | |
else | |
OCTOPRINT_VERSION="${{ github.event.inputs.octoprint_version }}" | |
echo "Version from workflow dispatch: $OCTOPRINT_VERSION" | |
fi | |
if [ -z "$OCTOPRINT_VERSION" ]; then | |
OCTOPRINT_VERSION=$(curl https://pypi.org/pypi/OctoPrint/json -s | jq -r '.info.version') | |
echo "Version from PyPI: $OCTOPRINT_VERSION" | |
fi | |
# Make sure we have a published version | |
curl -fsSL --output /dev/null --head https://pypi.org/pypi/OctoPrint/$OCTOPRINT_VERSION/ || exit 1 | |
echo "OctoPrint version: $OCTOPRINT_VERSION" | |
echo "OCTOPRINT_VERSION=$OCTOPRINT_VERSION" >> $GITHUB_ENV | |
- name: "⬇ Download OctoPi" | |
id: octopi_download | |
run: | | |
mkdir build | |
cd build | |
curl -L -o octopi.zip ${{ env.OCTOPI_URL }} | |
unzip octopi.zip | |
rm octopi.zip | |
IMAGE=$(ls *.img | head -n 1) | |
mv $IMAGE input.img | |
- name: "📝 Prepare release" | |
run: | | |
now=$(date +"%Y%m%d%H%M%S") | |
RELEASE_BUILD="build $now" | |
[ "$GITHUB_REF_NAME" != "main" ] && RELEASE_BUILD="$RELEASE_BUILD from branch $GITHUB_REF_NAME" | |
RELEASE_NAME="OctoPi ${{ env.OCTOPI_VERSION }} with OctoPrint ${{ env.OCTOPRINT_VERSION }} ($RELEASE_BUILD)" | |
echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV | |
RELEASE_TAG="${{ env.OCTOPI_VERSION }}-${{ env.OCTOPRINT_VERSION }}-$now" | |
echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_ENV | |
# release body | |
cat <<EOF > ./build/release.md | |
* OctoPi ${{ env.OCTOPI_VERSION }} | |
* OctoPrint ${{ env.OCTOPRINT_VERSION }} | |
* Latest versions of the bundled OctoPrint plugins | |
* Latest kernel & bootloader | |
* Latest libcamera-apps | |
* New camera-streamer based webcam stack | |
Created with [CustoPiZer](https://github.com/OctoPrint/CustoPiZer) | |
<!-- mark:untested --> | |
EOF | |
[ "$GITHUB_REF_NAME" != "main" ] && cat <<EOF >> ./build/release.md | |
<!-- mark:ignored --> | |
EOF | |
- name: "🏗 Run CustoPiZer" | |
uses: OctoPrint/CustoPiZer@main | |
with: | |
workspace: "${{ github.workspace }}/build" | |
scripts: "${{ github.workspace }}/scripts" | |
environment: '{ "OCTOPRINT_VERSION": "${{ env.OCTOPRINT_VERSION }}", "RELEASE_TAG": "${{ env.RELEASE_TAG }}" }' | |
- name: "✏ Rename image" | |
run: | | |
RELEASE_TAG="${{ env.RELEASE_TAG }}" | |
IMAGE="octopi-$RELEASE_TAG.img" | |
echo "IMAGE=$IMAGE" >> $GITHUB_ENV | |
cd build | |
mv output.img $IMAGE | |
- name: "📦 Package the image" | |
id: package-image | |
uses: OctoPrint/actions/package-rpi-image@main | |
with: | |
image_path: "build/${{ env.IMAGE }}" | |
- name: 📨 Export zip name and URL to env | |
run: | | |
echo "IMAGE_ZIP=${{ steps.package-image.outputs.zip_name }}" >> $GITHUB_ENV | |
echo "IMAGE_URL=https://github.com/OctoPrint/OctoPi-UpToDate/releases/download/${{ env.RELEASE_TAG }}/${{ steps.package-image.outputs.zip_name }}" >> $GITHUB_ENV | |
- name: "🆕 Generate rpi-imager.json snippet" | |
uses: OctoPrint/actions/rpi-imager-snippet@main | |
with: | |
name: "${{ env.RELEASE_NAME }}" | |
description: "A Raspberry Pi distribution for 3d printers. Ships OctoPrint ${{ env.OCTOPRINT_VERSION }} out-of-the-box." | |
icon: "https://octopi.octoprint.org/rpi-imager.png" | |
url: "${{ env.IMAGE_URL }}" | |
output: "build/rpi-imager.json" | |
image_sha256: ${{ steps.package-image.outputs.image_sha256 }} | |
image_size: ${{ steps.package-image.outputs.image_size }} | |
zip_sha256: ${{ steps.package-image.outputs.zip_sha256 }} | |
zip_size: ${{ steps.package-image.outputs.zip_size }} | |
devices: "pi4-32bit,pi3-32bit,pi2-32bit,pi1-32bit" | |
- name: "🔖 Create release & attach assets" | |
uses: softprops/action-gh-release@v1 | |
with: | |
name: "${{ env.RELEASE_NAME }}" | |
tag_name: "${{ env.RELEASE_TAG }}" | |
body_path: "build/release.md" | |
prerelease: ${{ github.ref != 'refs/heads/main' || contains(env.OCTOPRINT_VERSION, 'rc') || contains(env.OCTOPI_VERSION, 'rc') }} | |
fail_on_unmatched_files: true | |
files: | | |
build/${{ env.IMAGE_ZIP }} | |
build/${{ env.IMAGE_ZIP }}.md5 | |
build/${{ env.IMAGE_ZIP }}.sha256 | |
build/rpi-imager.json | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
test: | |
name: "Test" | |
runs-on: ubuntu-latest | |
needs: build | |
steps: | |
- name: 🏃♀️ Run test against testrig | |
uses: jonas-schievink/workflow-proxy@v1 | |
with: | |
token: ${{ secrets.DISPATCH_TOKEN }} | |
workflow: Test against testrig | |
repo: OctoPrint/devtools | |
ref: main | |
inputs: '{"image": "${{ needs.build.outputs.image-url }}", "target": "pic"}' | |
repost-logs: false | |
deploy: | |
name: "Deploy" | |
runs-on: ubuntu-latest | |
needs: [build, test] | |
environment: live | |
steps: | |
- uses: actions/github-script@v7 | |
name: "✔ Mark release as tested" | |
env: | |
TAG: "${{ needs.build.outputs.tag }}" | |
with: | |
script: | | |
const { TAG } = process.env; | |
const owner = context.repo.owner; | |
const repo = context.repo.repo; | |
const marker = "<!-- mark:untested -->"; | |
github.rest.repos.getReleaseByTag({ | |
owner: owner, | |
repo: repo, | |
tag: TAG | |
}).then(release => { | |
release.data.body = release.data.body.replace(marker, "") | |
return github.rest.repos.updateRelease({ | |
owner: owner, | |
repo: repo, | |
release_id: release.data.id, | |
body: release.data.body | |
}) | |
}).catch(err => { | |
console.error(err) | |
throw new Error(`Could not update release ${TAG}`) | |
}) |