mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 20:03:53 +08:00
* ci: enhance pull request handling for prebuilt workflows * ci: add wait-for-action step to monitor selfdrive_tests workflow * ci: add validation job to monitor selfdrive_tests for prebuilt workflows * test * force negative condition to validate flow * force negative condition to validate flow * ci: add wait_for_tests input to control selfdrive_tests workflow execution * ci: update description for wait_for_tests input in workflow * Cleaning * Remove PR label when triggered by the label * Rename * Changing to target and only caring about labeled for the time being * gh action needs cancelled not canceled * Line ending
311 lines
13 KiB
YAML
311 lines
13 KiB
YAML
name: sunnypilot prebuilt action
|
||
|
||
env:
|
||
BUILD_DIR: "/data/openpilot"
|
||
OUTPUT_DIR: ${{ github.workspace }}/output
|
||
CI_DIR: ${{ github.workspace }}/release/ci
|
||
SCONS_CACHE_DIR: ${{ github.workspace }}/release/ci/scons_cache
|
||
PUBLIC_REPO_URL: "https://github.com/sunnypilot/sunnypilot"
|
||
|
||
# Branch configurations
|
||
MASTER_BRANCH: "master"
|
||
MASTER_NEW_BRANCH: "master-new"
|
||
DEV_C3_SOURCE_BRANCH: "master-dev-c3-new"
|
||
|
||
# Target branch configurations
|
||
STAGING_TARGET_BRANCH: "staging-c3-new"
|
||
DEV_TARGET_BRANCH: "dev-c3-new"
|
||
RELEASE_TARGET_BRANCH: "release-c3-new"
|
||
|
||
on:
|
||
push:
|
||
branches: [ master, master-new, master-dev-c3-new ]
|
||
tags: [ '*' ]
|
||
pull_request_target:
|
||
types: [ labeled ]
|
||
workflow_dispatch:
|
||
inputs:
|
||
wait_for_tests:
|
||
description: 'Wait for selfdrive_tests to finish'
|
||
required: false
|
||
type: boolean
|
||
default: false
|
||
|
||
jobs:
|
||
validate_tests:
|
||
runs-on: ubuntu-24.04
|
||
if: ((github.event_name == 'workflow_dispatch' && inputs.wait_for_tests) || contains('pull_request', github.event_name) && (github.event.action == 'labeled' && github.event.label.name == 'prebuilt'))
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- name: Wait for Tests
|
||
uses: ./.github/workflows/wait-for-action # Path to where you place the action
|
||
with:
|
||
workflow: selfdrive_tests.yaml # The workflow file to monitor
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
|
||
build:
|
||
needs: [ validate_tests ]
|
||
concurrency:
|
||
group: build-${{ github.head_ref || github.ref_name }}
|
||
cancel-in-progress: false
|
||
runs-on: self-hosted
|
||
outputs:
|
||
new_branch: ${{ steps.set-env.outputs.new_branch }}
|
||
version: ${{ steps.set-env.outputs.version }}
|
||
extra_version_identifier: ${{ steps.set-env.outputs.extra_version_identifier }}
|
||
commit_sha: ${{ steps.set-env.outputs.commit_sha }}
|
||
if: always() && !failure() && !cancelled()
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
with:
|
||
submodules: recursive
|
||
- run: git lfs pull
|
||
|
||
- name: Cache SCons
|
||
uses: actions/cache@v4
|
||
with:
|
||
path: ${{env.SCONS_CACHE_DIR}}
|
||
key: scons-${{ runner.os }}-${{ runner.arch }}-${{ github.head_ref || github.ref_name }}-${{ github.sha }}
|
||
# Note: GitHub Actions enforces cache isolation between different build sources (PR builds, workflow dispatches, etc.)
|
||
# for security. Only caches from the default branch are shared across all builds. This is by design and cannot be overridden.
|
||
restore-keys: |
|
||
scons-${{ runner.os }}-${{ runner.arch }}-${{ github.head_ref || github.ref_name }}
|
||
scons-${{ runner.os }}-${{ runner.arch }}-${{ env.MASTER_NEW_BRANCH }}
|
||
scons-${{ runner.os }}-${{ runner.arch }}-${{ env.MASTER_BRANCH }}
|
||
scons-${{ runner.os }}-${{ runner.arch }}
|
||
|
||
- name: Set Configuration
|
||
run: |
|
||
if [[ "${{ github.ref_name }}" == "${{ env.DEV_C3_SOURCE_BRANCH }}" ]]; then
|
||
# Dev configuration
|
||
echo "BRANCH_TYPE=dev" >> $GITHUB_ENV
|
||
echo "NEW_BRANCH=${{ env.DEV_TARGET_BRANCH }}" >> $GITHUB_ENV
|
||
echo "VERSION=$(date '+%Y.%m.%d')-${{ github.run_number }}" >> $GITHUB_ENV
|
||
echo "EXTRA_VERSION_IDENTIFIER=${{ github.run_number }}" >> $GITHUB_ENV
|
||
|
||
elif [[ "${{ github.ref_name }}" == "${{ env.MASTER_BRANCH }}" || "${{ github.ref_name }}" == "${{ env.MASTER_NEW_BRANCH }}" ]]; then
|
||
# Master configuration
|
||
echo "BRANCH_TYPE=master" >> $GITHUB_ENV
|
||
echo "NEW_BRANCH=${{ env.STAGING_TARGET_BRANCH }}" >> $GITHUB_ENV
|
||
echo "EXTRA_VERSION_IDENTIFIER=staging" >> $GITHUB_ENV
|
||
echo "VERSION=$(cat common/version.h | grep COMMA_VERSION | sed -e 's/[^0-9|.]//g')-staging" >> $GITHUB_ENV
|
||
|
||
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
||
# Tag configuration
|
||
echo "BRANCH_TYPE=tag" >> $GITHUB_ENV
|
||
echo "NEW_BRANCH=${{ env.RELEASE_TARGET_BRANCH }}" >> $GITHUB_ENV
|
||
echo "EXTRA_VERSION_IDENTIFIER=release" >> $GITHUB_ENV
|
||
echo "VERSION=$(cat common/version.h | grep COMMA_VERSION | sed -e 's/[^0-9|.]//g')-release" >> $GITHUB_ENV
|
||
|
||
else
|
||
# Feature branch configuration
|
||
echo "BRANCH_TYPE=dispatch" >> $GITHUB_ENV
|
||
echo "NEW_BRANCH=${{ github.head_ref || github.ref_name }}-prebuilt" >> $GITHUB_ENV
|
||
echo "VERSION=$(date '+%Y.%m.%d')-${{ github.run_number }}" >> $GITHUB_ENV
|
||
fi
|
||
|
||
- name: Set environment variables
|
||
id: set-env
|
||
run: |
|
||
# Write to GITHUB_OUTPUT from environment variables
|
||
echo "new_branch=$NEW_BRANCH" >> $GITHUB_OUTPUT
|
||
[[ ! -z "$EXTRA_VERSION_IDENTIFIER" ]] && echo "extra_version_identifier=$EXTRA_VERSION_IDENTIFIER" >> $GITHUB_OUTPUT
|
||
[[ ! -z "$VERSION" ]] && echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||
echo "commit_sha=${{ github.sha }}" >> $GITHUB_OUTPUT
|
||
|
||
# Set up common environment
|
||
source /etc/profile;
|
||
export UV_PROJECT_ENVIRONMENT=${HOME}/venv
|
||
export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT
|
||
printenv >> $GITHUB_ENV
|
||
if [[ "${{ runner.debug }}" == "1" ]]; then
|
||
cat $GITHUB_OUTPUT
|
||
fi
|
||
|
||
- name: Setup build environment
|
||
run: |
|
||
mkdir -p "${BUILD_DIR}/"
|
||
sudo find $BUILD_DIR/ -mindepth 1 -delete
|
||
echo "Starting build stage..."
|
||
echo "BUILD_DIR: ${BUILD_DIR}"
|
||
echo "CI_DIR: ${CI_DIR}"
|
||
echo "VERSION: ${{ steps.set-env.outputs.version }}"
|
||
echo "UV_PROJECT_ENVIRONMENT: ${UV_PROJECT_ENVIRONMENT}"
|
||
echo "VIRTUAL_ENV: ${VIRTUAL_ENV}"
|
||
echo "-------"
|
||
if [[ "${{ runner.debug }}" == "1" ]]; then
|
||
printenv
|
||
fi
|
||
PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --disable
|
||
|
||
- name: Build Main Project
|
||
run: |
|
||
export PYTHONPATH="$BUILD_DIR"
|
||
./release/release_files.py | sort | uniq | rsync -rRl${RUNNER_DEBUG:+v} --files-from=- . $BUILD_DIR/
|
||
cd $BUILD_DIR
|
||
sed -i '/from .board.jungle import PandaJungle, PandaJungleDFU/s/^/#/' panda/__init__.py
|
||
scons -j$(nproc) cache_dir=${{env.SCONS_CACHE_DIR}} --minimal
|
||
touch ${BUILD_DIR}/prebuilt
|
||
if [[ "${{ runner.debug }}" == "1" ]]; then
|
||
ls -la ${BUILD_DIR}
|
||
fi
|
||
|
||
- name: Prepare Output
|
||
run: |
|
||
sudo rm -rf ${OUTPUT_DIR}
|
||
mkdir -p ${OUTPUT_DIR}
|
||
rsync -am${RUNNER_DEBUG:+v} \
|
||
--include='**/panda/board/' \
|
||
--include='**/panda/board/obj' \
|
||
--include='**/panda/board/obj/panda.bin.signed' \
|
||
--include='**/panda/board/obj/panda_h7.bin.signed' \
|
||
--include='**/panda/board/obj/bootstub.panda.bin' \
|
||
--include='**/panda/board/obj/bootstub.panda_h7.bin' \
|
||
--exclude='.sconsign.dblite' \
|
||
--exclude='*.a' \
|
||
--exclude='*.o' \
|
||
--exclude='*.os' \
|
||
--exclude='*.pyc' \
|
||
--exclude='moc_*' \
|
||
--exclude='*.cc' \
|
||
--exclude='Jenkinsfile' \
|
||
--exclude='supercombo.onnx' \
|
||
--exclude='**/panda/board/*' \
|
||
--exclude='**/panda/board/obj/**' \
|
||
--exclude='**/panda/certs/' \
|
||
--exclude='**/panda/crypto/' \
|
||
--exclude='**/release/' \
|
||
--exclude='**/.github/' \
|
||
--exclude='**/selfdrive/ui/replay/' \
|
||
--exclude='**/__pycache__/' \
|
||
--exclude='**/selfdrive/ui/*.h' \
|
||
--exclude='**/selfdrive/ui/**/*.h' \
|
||
--exclude='**/selfdrive/ui/qt/offroad/sunnypilot/' \
|
||
--exclude='${{env.SCONS_CACHE_DIR}}' \
|
||
--exclude='**/.git/' \
|
||
--exclude='**/SConstruct' \
|
||
--exclude='**/SConscript' \
|
||
--exclude='**/.venv/' \
|
||
--delete-excluded \
|
||
--chown=comma:comma \
|
||
${BUILD_DIR}/ ${OUTPUT_DIR}/
|
||
|
||
- name: 'Tar.gz files'
|
||
run: |
|
||
tar czf prebuilt.tar.gz -C ${{ env.OUTPUT_DIR }} .
|
||
ls -la prebuilt.tar.gz
|
||
|
||
- name: 'Upload Artifact'
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: prebuilt
|
||
path: prebuilt.tar.gz
|
||
|
||
- name: Re-enable powersave
|
||
if: always()
|
||
run: |
|
||
PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --enable
|
||
|
||
publish:
|
||
concurrency:
|
||
group: publish-${{ github.head_ref || github.ref_name }}
|
||
cancel-in-progress: true
|
||
if: ${{ !contains('pull_request', github.event_name) || (github.event.action == 'labeled' && github.event.label.name == 'prebuilt') }}
|
||
needs: build
|
||
runs-on: ubuntu-24.04
|
||
environment: ${{ (contains(fromJSON(vars.AUTO_DEPLOY_PREBUILT_BRANCHES), github.head_ref || github.ref_name) || contains(github.event.pull_request.labels.*.name, 'prebuilt')) && 'auto-deploy' || 'feature-branch' }}
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Download build artifacts
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: prebuilt
|
||
|
||
- name: Untar prebuilt
|
||
run: |
|
||
mkdir -p ${{ env.OUTPUT_DIR }}
|
||
tar xzf prebuilt.tar.gz -C ${{ env.OUTPUT_DIR }}
|
||
|
||
- name: Configure Git
|
||
run: |
|
||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||
git config --global user.name "github-actions[bot]"
|
||
|
||
- name: Publish to Public Repository
|
||
env:
|
||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
run: |
|
||
echo '${{ toJSON(needs.build.outputs) }}'
|
||
ls -la ${{ env.OUTPUT_DIR }}
|
||
|
||
${{ env.CI_DIR }}/publish.sh \
|
||
"${{ github.workspace }}" \
|
||
"${{ env.OUTPUT_DIR }}" \
|
||
"${{ needs.build.outputs.new_branch }}" \
|
||
"${{ needs.build.outputs.version }}" \
|
||
"https://x-access-token:${{github.token}}@github.com/sunnypilot/sunnypilot.git" \
|
||
"-${{ needs.build.outputs.extra_version_identifier }}"
|
||
|
||
echo ""
|
||
echo "---- ℹ️ To update the list of branches that auto deploy prebuilts -----"
|
||
echo ""
|
||
echo "1. Go to: ${{ github.server_url }}/${{ github.repository }}/settings/variables/actions/AUTO_DEPLOY_PREBUILT_BRANCHES"
|
||
echo "2. Current value: ${{ vars.AUTO_DEPLOY_PREBUILT_BRANCHES }}"
|
||
echo "3. Update as needed (JSON array with no spaces)"
|
||
|
||
notify:
|
||
needs: [ build, publish ]
|
||
runs-on: ubuntu-24.04
|
||
if: success()
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- name: Setup Alpine Linux environment
|
||
uses: jirutka/setup-alpine@v1.2.0
|
||
with:
|
||
packages: 'jq gettext curl'
|
||
|
||
- name: Send Discord Notification
|
||
env:
|
||
DISCORD_WEBHOOK: ${{ contains(fromJSON(vars.DEV_FEEDBACK_NOTIFICATION_BRANCHES), github.head_ref || github.ref_name) && secrets.DISCORD_DEV_FEEDBACK_CHANNEL_WEBHOOK || secrets.DISCORD_DEV_PRIVATE_CHANNEL_WEBHOOK }}
|
||
run: |
|
||
TEMPLATE='${{ vars.DISCORD_GENERAL_UPDATE_NOTICE }}'
|
||
export EXTRA_VERSION_IDENTIFIER="${{ needs.build.outputs.extra_version_identifier }}"
|
||
export VERSION="${{ needs.build.outputs.version }}"
|
||
export branch_name=${{ github.head_ref || github.ref_name }}
|
||
export new_branch=${{ needs.build.outputs.new_branch }}
|
||
export extra_version_identifier=${{ needs.build.outputs.extra_version_identifier || github.run_number}}
|
||
echo ${TEMPLATE} | envsubst | jq -c '.' | tee payload.json
|
||
curl -X POST -H "Content-Type: application/json" -d @payload.json $DISCORD_WEBHOOK
|
||
|
||
echo ""
|
||
echo "---- ℹ️ To update the list of branches that notify to dev-feedback -----"
|
||
echo ""
|
||
echo "1. Go to: ${{ github.server_url }}/${{ github.repository }}/settings/variables/actions/DEV_FEEDBACK_NOTIFICATION_BRANCHES"
|
||
echo "2. Current value: ${{ vars.DEV_FEEDBACK_NOTIFICATION_BRANCHES }}"
|
||
echo "3. Update as needed (JSON array with no spaces)"
|
||
shell: alpine.sh {0}
|
||
|
||
manage-pr-labels:
|
||
name: Remove prebuilt label
|
||
runs-on: ubuntu-latest
|
||
if: (always() && contains('pull_request', github.event_name) && (github.event.action == 'labeled' && github.event.label.name == 'prebuilt'))
|
||
env:
|
||
LABEL: prebuilt
|
||
steps:
|
||
- name: Remove trust-fork-pr label if present
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const prNumber = context.payload.pull_request.number;
|
||
|
||
await github.rest.issues.removeLabel({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: prNumber,
|
||
name: process.env.LABEL
|
||
});
|
||
|
||
console.log(`Removed '${process.env.LABEL}' label from PR #${prNumber}`);
|