diff --git a/.github/actions/compile/action.yml b/.github/actions/compile/action.yml new file mode 100644 index 00000000..eed0074c --- /dev/null +++ b/.github/actions/compile/action.yml @@ -0,0 +1,141 @@ +name: Run kas for a specific build configuration +inputs: + machine: + required: true + distro_yaml: + required: true + distro_name: + required: true + kernel_yaml: + required: true + kernel_dirname: + required: true + cache_dir: + required: true + sdk: + required: false + default: "0" +outputs: + url: + description: Location of the published binaries + value: ${{ steps.upload_artifacts.outputs.url }} +runs: + using: "composite" + steps: + - name: Download kas lockfile + uses: actions/download-artifact@v6 + with: + name: kas-lockfile + path: ci/ + + - name: Download kas-container + uses: actions/download-artifact@v6 + with: + name: kas-container + path: ${{runner.temp}} + + - name: Setting up kas-container + shell: bash + run: | + KAS_CONTAINER=$RUNNER_TEMP/kas-container + echo "KAS_CONTAINER=$KAS_CONTAINER" >> $GITHUB_ENV + chmod +x $KAS_CONTAINER + + - name: Setup build variables and sstate-cache + shell: bash + run: | + # use a monthly sstate cache folder + echo "DL_DIR=${{inputs.cache_dir}}/downloads" >> $GITHUB_ENV + echo "SSTATE_DIR=${{inputs.cache_dir}}/sstate-cache-$(date '+%Y-%m')" >> $GITHUB_ENV + echo "KAS_WORK_DIR=$PWD/../kas" >> $GITHUB_ENV + + - name: Dump kas-build yaml + shell: bash + run: | + mkdir $KAS_WORK_DIR + $KAS_CONTAINER dump --resolve-env --resolve-local --resolve-refs \ + ci/mirror.yml:ci/${{ inputs.machine }}.yml${{ inputs.distro_yaml }}${{ inputs.kernel_yaml }} > kas-build.yml + + - name: Kas qcom world build + shell: bash + run: | + $KAS_CONTAINER build ci/mirror.yml:ci/${{ inputs.machine }}.yml${{ inputs.distro_yaml }}${{ inputs.kernel_yaml }}:ci/world.yml + ci/kas-container-shell-helper.sh ci/yocto-pybootchartgui.sh + mv $KAS_WORK_DIR/build/buildchart.svg buildchart-world.svg + + - name: Kas build images + shell: bash + run: | + $KAS_CONTAINER build ci/mirror.yml:ci/${{ inputs.machine }}.yml${{ inputs.distro_yaml }}${{ inputs.kernel_yaml }} + ci/kas-container-shell-helper.sh ci/yocto-pybootchartgui.sh + mv $KAS_WORK_DIR/build/buildchart.svg . + + if [ "${{ inputs.machine }}" = "qcom-armv8a" ]; then + $KAS_CONTAINER build ci/mirror.yml:ci/${{ inputs.machine }}.yml${{ inputs.distro_yaml }}${{ inputs.kernel_yaml }}:ci/initramfs-test.yml + + # SDK only with the default kernel + if [ "${{ inputs.sdk }}" = "1" ] && [ "${{ inputs.kernel_yaml }}" = "" ] ; then + $KAS_CONTAINER build ci/mirror.yml:ci/${{ inputs.machine }}.yml${{ inputs.distro_yaml }}${{ inputs.kernel_yaml }} --task populate_sdk + fi + fi + + - uses: actions/upload-artifact@v6 + with: + name: buildchart-${{ inputs.distro_name }}${{ inputs.kernel_dirname }}-${{ inputs.machine }} + path: | + buildchart.svg + buildchart-world.svg + + - uses: actions/upload-artifact@v6 + with: + name: kas-build-${{ inputs.distro_name }}${{ inputs.kernel_dirname }}-${{ inputs.machine }} + path: kas-build.yml + + - name: Stage build artifacts for publishing + shell: bash + run: | + # The upload-private-artifact-action runs from a container that + # expects file to be relative to our PWD. deploy_dir is outside + # that, so we move things around: + deploy_dir=../kas/build/tmp/deploy/images/${{inputs.machine}} + uploads_dir=./uploads/${{ inputs.distro_name }}${{ inputs.kernel_dirname }}/${{ inputs.machine }} + mkdir -p $uploads_dir + # Publish everything that is linked by bitbake at the end of the build (avoid timestamp and duplication) + find $deploy_dir/ -maxdepth 1 -type l -exec cp --dereference {} $uploads_dir/ \; + # Files without links: *.vfat, *.elf, *.efi, efi.stub, fit *.its, qcom-metadata.dtb and qclinuxfitImage + # Copy *.efi, *.efi and *.vfat as they are useful for debugging + find $deploy_dir/ -maxdepth 1 -type f \( -name \*.efi -o -name \*.elf -o -name dtb-\*.vfat \) -exec cp {} $uploads_dir/ \; + cp buildchart.svg kas-build.yml $uploads_dir/ + if [ -d $deploy_dir/../../sdk ]; then + cp $deploy_dir/../../sdk/* $uploads_dir/ + fi + + - name: Upload private artifacts + uses: qualcomm-linux/upload-private-artifact-action@v1 + id: upload_artifacts + with: + path: ./uploads + + - name: Upload artifacts to S3 bucket + uses: qualcomm-linux/upload-private-artifact-action@aws-v1 + with: + path: ./uploads + destination: ${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ github.run_id }}-${{ github.run_attempt }}/ + s3_bucket: qcom-prd-gh-artifacts + + - name: "Print output" + shell: bash + id: print-output + run: | + KERNEL_DIRNAME="${{ inputs.kernel_dirname }}" + BUILDNAME="${{ inputs.machine }}_${{ inputs.distro_name }}${KERNEL_DIRNAME}" + FILENAME="build-url_${BUILDNAME}" + echo "${{ steps.upload_artifacts.outputs.url }}" > "${FILENAME}" + echo "filename=${FILENAME}" >> $GITHUB_OUTPUT + - name: Upload build URL + uses: actions/upload-artifact@v6 + with: + overwrite: true + name: ${{ steps.print-output.outputs.filename }} + path: ${{ steps.print-output.outputs.filename }} + diff --git a/.github/workflows/build-yocto.yml b/.github/workflows/build-yocto.yml new file mode 100644 index 00000000..336e0c7b --- /dev/null +++ b/.github/workflows/build-yocto.yml @@ -0,0 +1,280 @@ +name: Build Yocto + +on: + workflow_call: + inputs: + sdk: + required: false + type: string + default: "0" + outputs: + artifacts_url: + description: "URL to retrieve build artifacts" + value: ${{ jobs.create-output.outputs.url }} + +# Concurrency is used to prevent multiple workflows from running for the same PR +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + CACHE_DIR: /efs/qli/meta-qcom + KAS_REPO_REF_DIR: /efs/qli/meta-qcom/kas-mirrors + +jobs: + kas-setup: + if: github.repository_owner == 'qualcomm-linux' + runs-on: [self-hosted, qcom-u2404, amd64] + steps: + - name: Setting up kas-container + run: | + KAS_CONTAINER=$RUNNER_TEMP/kas-container + echo "KAS_CONTAINER=$KAS_CONTAINER" >> $GITHUB_ENV + LATEST=$(git ls-remote --tags --refs --sort="v:refname" https://github.com/siemens/kas | tail -n1 | sed 's/.*\///') + wget -qO ${KAS_CONTAINER} https://raw.githubusercontent.com/siemens/kas/refs/tags/$LATEST/kas-container + chmod +x ${KAS_CONTAINER} + + - name: Checkout meta-qcom + uses: actions/checkout@v4 + with: + repository: qualcomm-linux/meta-qcom + path: ${{ github.workspace }}/meta-qcom + + - name: Checkout meta-qcom-distro + uses: actions/checkout@v4 + with: + path: ${{ github.workspace }}/meta-qcom-distro + + - name: Run kas lock + run: | + KAS_CI_BASE=${GITHUB_WORKSPACE}/meta-qcom/ci/base.yml + KAS_CI_DISTRO=${GITHUB_WORKSPACE}/meta-qcom-distro/ci/qcom-distro.yml + ${KAS_CONTAINER} lock --update ${KAS_CI_BASE}:${KAS_CI_DISTRO} + + - name: Upload kas lockfile + uses: actions/upload-artifact@v6 + with: + name: kas-lockfile + path: ci/*.lock.yml + + - name: Upload kas-container + uses: actions/upload-artifact@v4 + with: + name: kas-container + path: ${{ env.KAS_CONTAINER }} + + compile_warm_up: + needs: kas-setup + if: github.repository_owner == 'qualcomm-linux' + runs-on: [self-hosted, qcom-u2404, amd64] + strategy: + fail-fast: true + matrix: + machine: + - rb3gen2-core-kit + - qcom-armv8a + distro: + - name: qcom-distro + yamlfile: ':ci/qcom-distro-prop-image.yml' + - name: qcom-distro-selinux + yamlfile: ':ci/qcom-distro-selinux.yml' + - name: qcom-distro-sota + yamlfile: ':ci/qcom-distro-sota.yml' + kernel: + - type: default + dirname: "" + yamlfile: "" + - type: 6.18 + dirname: "+linux-qcom-6.18" + yamlfile: ":ci/linux-qcom-6.18.yml" + name: ${{ matrix.machine }}/${{ matrix.distro.name }}${{ matrix.kernel.dirname }} + steps: + - uses: actions/checkout@v4 + + - name: Run kas build + uses: ./.github/actions/compile + with: + machine: ${{matrix.machine}} + distro_yaml: ${{matrix.distro.yamlfile}} + distro_name: ${{matrix.distro.name}} + kernel_yaml: ${{matrix.kernel.yamlfile}} + kernel_dirname: ${{matrix.kernel.dirname}} + cache_dir: ${CACHE_DIR} + sdk: ${{inputs.sdk}} + + compile: + needs: compile_warm_up + if: github.repository_owner == 'qualcomm-linux' + runs-on: [self-hosted, qcom-u2404, amd64] + outputs: + url: ${{ steps.compile_kas.outputs.url }} + strategy: + fail-fast: true + matrix: + machine: + - iq-8275-evk + - iq-9075-evk + - iq-x7181-evk + - kaanapali-mtp + - qcm6490-idp + - qcs615-ride + - qcs8300-ride-sx + - qcs9100-ride-sx + - rb1-core-kit + - sm8750-mtp + distro: + - name: qcom-distro + yamlfile: ':ci/qcom-distro-prop-image.yml' + - name: qcom-distro-selinux + yamlfile: ':ci/qcom-distro-selinux.yml' + - name: qcom-distro-sota + yamlfile: ':ci/qcom-distro-sota.yml' + kernel: + - type: default + dirname: "" + yamlfile: "" + - type: 6.18 + dirname: "+linux-qcom-6.18" + yamlfile: ":ci/linux-qcom-6.18.yml" + include: + # Additional builds for specific machines + - machine: qcom-armv8a + distro: + name: qcom-distro + yamlfile: ':ci/qcom-distro-prop-image.yml' + kernel: + type: additional + dirname: "+linux-yocto-dev" + yamlfile: ":ci/linux-yocto-dev.yml" + - machine: iq-9075-evk + distro: + name: qcom-distro + yamlfile: ':ci/qcom-distro-prop-image.yml' + kernel: + type: rt-6.18 + dirname: "+linux-qcom-rt-6.18" + yamlfile: ":ci/linux-qcom-rt-6.18.yml" + - machine: iq-9075-evk + distro: + name: qcom-distro + yamlfile: ':ci/qcom-distro-prop-image.yml' + kernel: + type: qcom-next-rt + dirname: "+linux-qcom-next-rt" + yamlfile: ":ci/linux-qcom-next-rt.yml" + - machine: iq-9075-evk + distro: + name: performance + yamlfile: ':ci/qcom-distro-prop-image.yml:ci/performance.yml' + kernel: + type: 6.18 + dirname: "+linux-qcom-6.18" + yamlfile: ":ci/linux-qcom-6.18.yml" + - machine: iq-9075-evk + distro: + name: qcom-distro-kvm + yamlfile: ':ci/qcom-distro-kvm.yml' + kernel: + type: default + dirname: "" + yamlfile: "" + - machine: iq-8275-evk + distro: + name: performance + yamlfile: ':ci/qcom-distro-prop-image.yml:ci/performance.yml' + kernel: + type: 6.18 + dirname: "+linux-qcom-6.18" + yamlfile: ":ci/linux-qcom-6.18.yml" + - machine: iq-8275-evk + distro: + name: qcom-distro-kvm + yamlfile: ':ci/qcom-distro-kvm.yml' + kernel: + type: default + dirname: "" + yamlfile: "" + - machine: qcom-armv7a + distro: + name: qcom-distro + yamlfile: ':ci/qcom-distro.yml' + kernel: + type: default + dirname: "" + yamlfile: "" + name: ${{ matrix.machine }}/${{ matrix.distro.name }}${{ matrix.kernel.dirname }} + steps: + - uses: actions/checkout@v4 + + - name: Run kas build + uses: ./.github/actions/compile + id: compile_kas + with: + machine: ${{matrix.machine}} + distro_yaml: ${{matrix.distro.yamlfile}} + distro_name: ${{matrix.distro.name}} + kernel_yaml: ${{matrix.kernel.yamlfile}} + kernel_dirname: ${{matrix.kernel.dirname}} + cache_dir: ${CACHE_DIR} + sdk: ${{inputs.sdk}} + + publish_summary: + needs: compile + runs-on: [self-hosted, qcom-u2404, amd64] + steps: + - name: 'Download build URLs' + uses: actions/download-artifact@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + pattern: build-url* + path: urlfiles + merge-multiple: true + + - name: "Print output" + shell: python + id: print-output + run: | + import os + ftable = {} + oslist = set() + machinelist = set() + for fname in os.listdir("./urlfiles"): + if fname.startswith("build-url"): + b, m, o = fname.split("_", 2) + oslist.add(o) + machinelist.add(m) + url = "" + with open(f"./urlfiles/{fname}", "r") as urlfile: + url = urlfile.read() + if not o in ftable: + ftable.update({o:{m: url}}) + else: + ftable[o].update({m: url}) + + table_str = "| |" + + for m in sorted(machinelist): + table_str += f" {m} |" + + table_str += "\n|" + for i in range(len(machinelist) + 1): + table_str += " ---- |" + + table_str += "\n" + + for o in sorted(ftable.keys()): + table_str += f"| {o} |" + for m in sorted(machinelist): + url = ftable[o].get(m) + if url: + url = url.strip() + table_str += f" [Files]({url}/{o}/{m}/) |" + else: + table_str += " |" + table_str += "\n" + summary_file_name = os.environ.get("GITHUB_STEP_SUMMARY") + if summary_file_name: + with open(summary_file_name, "a") as summaryfile: + summaryfile.write("## Download URLs\n") + summaryfile.write(table_str) + print(table_str) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 00000000..fe893ef1 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,28 @@ +name: Build on PR + +on: + pull_request: + paths-ignore: + - 'README.md' + - 'README' + - 'SECURITY.md' + +permissions: + checks: write + pull-requests: write + contents: read + packages: read + +jobs: + event-file: + name: "Upload event file" + runs-on: ubuntu-latest + steps: + - name: Upload + uses: actions/upload-artifact@v6 + with: + name: Event File + path: ${{ github.event_path }} + build-pr: + uses: ./.github/workflows/build-yocto.yml + diff --git a/.github/workflows/publish-results.yml b/.github/workflows/publish-results.yml new file mode 100644 index 00000000..1567eb85 --- /dev/null +++ b/.github/workflows/publish-results.yml @@ -0,0 +1,73 @@ +name: Publish test results + +on: + workflow_call: + inputs: + workflow_id: + required: true + type: string + event_name: + required: true + type: string + event_file: + required: true + type: string + commit: + required: true + type: string + +permissions: + checks: write + pull-requests: write + contents: read + packages: read + +jobs: + publish-test-results: + name: "Publish Tests Results" + runs-on: ubuntu-latest + steps: + - name: Download result files + uses: actions/download-artifact@v6 + with: + run-id: ${{ inputs.workflow_id }} + path: artifacts + github-token: ${{ github.token }} + + - name: Download result files PR + if: ${{ github.run_id != inputs.workflow_id }} + uses: actions/download-artifact@v6 + with: + path: artifacts + github-token: ${{ github.token }} + + - name: "List files" + id: listfiles + run: | + echo $GITHUB_WORKSPACE + ls -R $GITHUB_WORKSPACE + if ! find "${{ github.workspace }}/artifacts/" -name '*.xml' -print -quit | grep -q .; then + echo "Error: no .xml files found" + exit 1 + fi + + - id: app_token + uses: actions/create-github-app-token@v2 + if: always() + with: + app-id: 2291458 + private-key: ${{ secrets.TEST_REPORTING_APP_TOKEN }} + + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: | + always() + && contains(steps.listfiles.outcome, 'success') + with: + commit: ${{ inputs.commit }} + event_file: ${{ inputs.event_file}} + event_name: ${{ inputs.event_name }} + files: "${{ github.workspace }}/artifacts/**/*.xml" + action_fail: true + action_fail_on_inconclusive: true + github_token: ${{ steps.app_token.outputs.token }} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 00000000..a3f2d605 --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,16 @@ +name: Build on push + +on: + push: + branches: + - main + +permissions: + checks: write + pull-requests: write + contents: read + packages: read + +jobs: + build: + uses: ./.github/workflows/build-yocto.yml diff --git a/.github/workflows/repolinter.yml b/.github/workflows/repolinter.yml new file mode 100644 index 00000000..aff3ca2e --- /dev/null +++ b/.github/workflows/repolinter.yml @@ -0,0 +1,31 @@ +name: QuIC Organization Repolinter + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + repolinter: + if: github.repository_owner == 'qualcomm-linux' + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Verify repolinter config file is present + id: check_files + uses: andstor/file-existence-action@v3 + with: + files: "repolint.json" + - name: Run Repolinter with local repolint.json + if: steps.check_files.outputs.files_exists == 'true' + uses: todogroup/repolinter-action@v1 + with: + config_file: "repolint.json" + - name: Run Repolinter with default ruleset + if: steps.check_files.outputs.files_exists == 'false' + uses: todogroup/repolinter-action@v1 + with: + config_url: "https://raw.githubusercontent.com/quic/.github/main/repolint.json" diff --git a/.github/workflows/stales.yml b/.github/workflows/stales.yml new file mode 100644 index 00000000..0a8685c0 --- /dev/null +++ b/.github/workflows/stales.yml @@ -0,0 +1,25 @@ +name: 'Close stale issues and pull requests with no recent activity' +on: + schedule: + - cron: "30 1 * * *" + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + stale-issue-message: 'This issue has been marked as stale due to 30 days of inactivity. Please add a comment and close if it is resolved or if it is no longer relevant.' + stale-pr-message: 'This pull request has been marked as stale due to 30 days of inactivity. To prevent automatic closure in 5 days, remove the stale label or add a comment. You can reopen a closed pull request at any time.' + exempt-issue-labels: bug,enhancement + exempt-pr-labels: bug,enhancement + days-before-stale: 30 + days-before-close: 5 + days-before-issue-close: -1 + remove-stale-when-updated: true + remove-issue-stale-when-updated: true + remove-pr-stale-when-updated: true diff --git a/ci/qcom-distro-kvm.yml b/ci/qcom-distro-kvm.yml new file mode 100644 index 00000000..1a3ace09 --- /dev/null +++ b/ci/qcom-distro-kvm.yml @@ -0,0 +1,8 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json + +header: + version: 14 + includes: + - ci/qcom-distro.yml + +distro: qcom-distro-kvm diff --git a/ci/qcom-distro-prop-image.yml b/ci/qcom-distro-prop-image.yml new file mode 100644 index 00000000..cec2a629 --- /dev/null +++ b/ci/qcom-distro-prop-image.yml @@ -0,0 +1,11 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json + +header: + version: 14 + includes: + - ci/qcom-distro.yml + +target: + - qcom-multimedia-image + - qcom-multimedia-proprietary-image + - qcom-container-orchestration-image diff --git a/ci/qcom-distro-selinux.yml b/ci/qcom-distro-selinux.yml new file mode 100644 index 00000000..bc9dd512 --- /dev/null +++ b/ci/qcom-distro-selinux.yml @@ -0,0 +1,12 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json + +header: + version: 14 + includes: + - ci/qcom-distro.yml + +distro: qcom-distro-selinux + +target: + - qcom-multimedia-image + - qcom-multimedia-proprietary-image diff --git a/ci/qcom-distro-sota.yml b/ci/qcom-distro-sota.yml new file mode 100644 index 00000000..84d6ea4e --- /dev/null +++ b/ci/qcom-distro-sota.yml @@ -0,0 +1,8 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json + +header: + version: 14 + includes: + - ci/qcom-distro.yml + +distro: qcom-distro-sota diff --git a/ci/qcom-distro.yml b/ci/qcom-distro.yml new file mode 100644 index 00000000..6bb11bea --- /dev/null +++ b/ci/qcom-distro.yml @@ -0,0 +1,50 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json + +header: + version: 14 + includes: + - repo: meta-qcom + file: ci/base.yml + +distro: qcom-distro + +repos: + meta-qcom-distro: + + meta-qcom: + branch: master + url: https://github.com/qualcomm-linux/meta-qcom + + meta-openembedded: + url: https://github.com/openembedded/meta-openembedded + layers: + meta-filesystems: + meta-gnome: + meta-multimedia: + meta-networking: + meta-oe: + meta-python: + meta-xfce: + + meta-virtualization: + url: https://git.yoctoproject.org/git/meta-virtualization + branch: master + + meta-audioreach: + url: https://github.com/AudioReach/meta-audioreach + branch: master + + meta-selinux: + branch: master + url: https://git.yoctoproject.org/meta-selinux + + meta-updater: + branch: master + url: https://github.com/uptane/meta-updater + +local_conf_header: + virtualization: + SKIP_META_VIRT_SANITY_CHECK = "1" + +target: + - qcom-multimedia-image