From a00328613bee562f816769bd2c4c518aef5f29ef Mon Sep 17 00:00:00 2001 From: Simon Beaudoin Date: Tue, 10 Feb 2026 13:46:29 -0800 Subject: [PATCH] release wf: Adding apt arficactory upload Signed-off-by: Simon Beaudoin --- .github/actions/upload/action.yml | 246 ++++++++++++++++++ .../qcom-release-reusable-workflow.yml | 55 ++-- 2 files changed, 285 insertions(+), 16 deletions(-) create mode 100644 .github/actions/upload/action.yml diff --git a/.github/actions/upload/action.yml b/.github/actions/upload/action.yml new file mode 100644 index 00000000..aec62ab2 --- /dev/null +++ b/.github/actions/upload/action.yml @@ -0,0 +1,246 @@ +name: "Upload Debian to Artifactory" +description: "Uploads Debian artifacts from a .changes file to Artifactory" + +inputs: + server_url: + description: "Artifactory server URL" + required: false + default: "https://qartifactory.pe.jfrog.io" + + target_base_repo: + description: "Target repo name (e.g. deb-local or deb-remote)" + required: false + default: "qsc-debian-local" + + changes_path: + description: "Path to .changes file" + required: true + + provenance_info: + description: "Extra artifactory properties" + required: false + default: "{}" + + access_token: + description: "Artifactory access token (mutually exclusive with qsc_api_key)" + required: false + + qsc_api_key: + description: "QSC API key - used to generate a temporary access token (mutually exclusive with access_token)" + required: false + + access_token_data: + description: "Access token data for generating access token - used in conjunction with qsc_api_key" + required: false + default: "{\"softwareName\":\"LU.QCLINUX\",\"softwareType\":\"SoftwareImage\",\"releaseTag\":\"2.0\"}" + + component: + description: "Component name" + required: false + default: "main" + + debug: + description: "Enable debug output directory in target repo (appends {{github.run_id}} to target path)" + required: false + default: false + +runs: + using: "composite" + steps: + + # This step checks for the presence of required Debian packaging tools and installs them if they are missing. + # The user is encouraged to install these dependencies in their environment beforehand to speed up the workflow, + # but this step ensures that the action can run successfully even if they are not pre-installed. + - name: Install dependencies if needed + shell: bash + run: | + set -euo pipefail + + # Sudo if needed + SUDO=sudo + if [ "$(id -u)" = 0 ]; then SUDO=""; fi + + # List the debian package names you require + required=(devscripts dctrl-tools jq curl) + + # Collect missing packages + missing=() + for pkg in "${required[@]}"; do + if ! dpkg -s "$pkg" >/dev/null 2>&1; then + missing+=("$pkg") + fi + done + + # Install only if something is missing + if ((${#missing[@]})); then + echo "Installing missing packages: ${missing[*]}" + # Noninteractive + lean + quiet + export DEBIAN_FRONTEND=noninteractive + $SUDO apt-get update -y -qq + $SUDO apt-get install -y -qq --no-install-recommends "${missing[@]}" + else + echo "All prerequisites already installed." + fi + + - name: Setup JFrog CLI + uses: jfrog/setup-jfrog-cli@v4 + with: + version: latest + + - name: Generate access token if qsc_api_key is provided, otherwise use provided access_token + id: gen_token + shell: bash + env: + ACCESS_TOKEN_URL: "https://apigwx-aws.qualcomm.com/saga/api/qsc/v1/chipSoftware/component/artifactory/release/artifact/debian/public/create/token" + run: | + set -euo pipefail + + if [ -z "${{ inputs.qsc_api_key }}" ] && [ -z "${{ inputs.access_token }}" ]; then + echo "ERROR: Neither qsc_api_key nor access_token provided." + exit 1 + fi + + if [ -n "${{ inputs.qsc_api_key }}" ] && [ -n "${{ inputs.access_token }}" ]; then + echo "ERROR: Both qsc_api_key and access_token were provided. These are not compatible." + exit 1 + fi + + if [ -n "${{ inputs.access_token }}" ]; then + echo "Using provided access_token..." + echo "access_token=${{ inputs.access_token }}" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "Generating access token using qsc_api_key..." + + response=$(curl -s \ + -X POST "${{env.ACCESS_TOKEN_URL}}" \ + -H 'Content-Type: application/json' \ + -H 'X-QCOM-TokenType: apikey' \ + -H 'Authorization: ${{ inputs.qsc_api_key }}' \ + -d '${{inputs.access_token_data}}') + + token=$(echo "$response" | jq -r '.token') + + if [ -z "$token" ] || [ "$token" = "null" ]; then + echo "ERROR: Failed to generate access token from qsc_api_key." + echo "Response was: $response" + exit 1 + fi + + echo "access_token=$token" >> $GITHUB_OUTPUT + echo "Access token generated successfully." + + - name: Determine changes-file directory + id: changes_dir + shell: bash + run: | + set -euo pipefail + + # compute directory portion of the provided changes_path (works if changes_path is a file or a directory) + CHANGES_FILE="${{ inputs.changes_path }}" + if [ -d "$CHANGES_FILE" ]; then + # input already a directory + dir="$CHANGES_FILE" + else + dir=$(dirname "$CHANGES_FILE") + fi + + echo "changes_file_dir=$dir" >> $GITHUB_OUTPUT + + - name: Parse .changes and provenance + working-directory: ${{ steps.changes_dir.outputs.changes_file_dir }} + shell: bash + env: + CHANGES_FILE_DIR: ${{ steps.changes_dir.outputs.changes_file_dir }} + PROVENANCE_INFO: ${{ inputs.provenance_info }} + run: | + set -euo pipefail + + shopt -s nullglob + + changes_files=( *.changes ) + + if (( ${#changes_files[@]} == 0 )); then + echo "ERROR: No .changes file found in $CHANGES_FILE_DIR" >&2 + exit 1 + fi + + if (( ${#changes_files[@]} > 1 )); then + echo "ERROR: Multiple .changes files found in $CHANGES_FILE_DIR: ${changes_files[*]}" >&2 + exit 1 + fi + + CHANGES_FILE="${changes_files[0]}" + echo "Using .changes file: $CHANGES_FILE" + + SUITE="$(grep-dctrl -ns Distribution . "$CHANGES_FILE")" + SOURCE_PKG="$(grep-dctrl -ns Source . "$CHANGES_FILE")" + ALL_FILES=$(grep-dctrl -nsFiles . "$CHANGES_FILE" | awk '{print $5}' | tr '\n' ' ') + + PROPS="deb.distribution=${SUITE};deb.component=${{ inputs.component }}" + + for key in $(echo "$PROVENANCE_INFO" | jq -r 'keys[]'); do + val=$(echo "$PROVENANCE_INFO" | jq -r --arg k "$key" '.[$k]') + PROPS="${PROPS};${key}=${val}" + done + + echo "ALL_FILES=$ALL_FILES" >> $GITHUB_ENV + echo "SOURCE_PKG=$SOURCE_PKG" >> $GITHUB_ENV + echo "SUITE=$SUITE" >> $GITHUB_ENV + echo "PROPS=$PROPS" >> $GITHUB_ENV + + echo "Parsed .changes file:" + echo " Distribution: $SUITE" + echo " Source Package: $SOURCE_PKG" + echo " All Files: $ALL_FILES" + echo " JFrog Properties: $PROPS" + + - name: Configure JFrog server + shell: bash + env: + SERVER_ID: "artifactory-server" + run: | + jf c add "$SERVER_ID" \ + --url "${{ inputs.server_url }}" \ + --access-token "${{ steps.gen_token.outputs.access_token }}" \ + --interactive=false \ + + echo "JFrog CLI configured with server ID '$SERVER_ID' and URL '${{ inputs.server_url }}'" + jf c show + + - name: Upload all artifacts with architecture detection + working-directory: ${{ inputs.changes_file_dir }} + shell: bash + env: + SERVER_ID: "artifactory-server" + run: | + TARGET_DIR="${{ inputs.target_base_repo }}/pool/$SOURCE_PKG/$SUITE/" + + if [ "${{ inputs.debug }}" = "true" ]; then + echo "Debug mode enabled - appending run_id to target directory" + echo "Original TARGET_DIR: $TARGET_DIR" + TARGET_DIR="$TARGET_DIR/${{github.run_id}}/" + echo "Modified TARGET_DIR: $TARGET_DIR" + fi + + for f in $ALL_FILES; do + + if [[ "$f" =~ _arm64\.deb$ || "$f" =~ _arm64\.ddeb$ ]]; then + PROPS="${PROPS};deb.architecture=arm64" + elif [[ "$f" =~ _amd64\.deb$ || "$f" =~ _amd64\.ddeb$ ]]; then + PROPS="${PROPS};deb.architecture=amd64" + fi + + echo "Uploading $f" + echo server_id: "$SERVER_ID" + echo "props: $PROPS" + echo "target: $TARGET_DIR" + + jf rt upload \ + --server-id="$SERVER_ID" \ + --target-props "${PROPS}" \ + "$f" \ + "$TARGET_DIR" + + done diff --git a/.github/workflows/qcom-release-reusable-workflow.yml b/.github/workflows/qcom-release-reusable-workflow.yml index 9ab1a5d9..c5e63f95 100644 --- a/.github/workflows/qcom-release-reusable-workflow.yml +++ b/.github/workflows/qcom-release-reusable-workflow.yml @@ -38,6 +38,8 @@ on: secrets: TOKEN: required: true + QSC_TOKEN: + required: true permissions: contents: read @@ -69,7 +71,6 @@ jobs: with: repository: qualcomm-linux/qcom-build-utils ref: ${{inputs.qcom-build-utils-ref}} - token: ${{secrets.TOKEN}} path: ./qcom-build-utils fetch-depth: 1 sparse-checkout: | @@ -188,7 +189,8 @@ jobs: "packages": $MAIN_PKGS_JSON, "dev-packages": $DEV_PKGS_JSON, - "build_timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" + "build_timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")", + "workflow_url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" } } EOF @@ -203,22 +205,11 @@ jobs: pkg-dir: package-repo build-dir: build - - name: Remove files with unauthorized characters - run: | - rm build/*.build - - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - with: - name: build-artifacts - path: build/ - # After the above step that changed the changlog from UNRELEASED to unstable, now create a new changelog entry # that bumps the version for the next development cycle and sets the suite back to UNRELEASED - name: Commit changelog suite change + working-directory: ./package-repo run: | - cd ./package-repo - version=$(dpkg-parsechangelog --show-field Version) # bump Debian revision (last hyphen-separated field), e.g. 1.0.0-1 -> 1.0.0-2 @@ -242,11 +233,32 @@ jobs: git commit -a -m "Initial commit of new version ${newversion}" - git push origin ${{inputs.debian-branch}} - git push origin debian/${version} + #TODO reactivate those + #git push origin ${{inputs.debian-branch}} + #git push origin debian/${version} git log --graph --oneline -n 10 --color=always + - name: Prepare build logs for upload + working-directory: ./build/ + run: | + # Remove symlink and rename timestamped .build file to its base name + BUILD_LINK=$(find . -maxdepth 1 -name "*.build" -type l) + if [ -n "$BUILD_LINK" ]; then + BUILD_TARGET=$(readlink "$BUILD_LINK") + rm "$BUILD_LINK" + mv "$BUILD_TARGET" "$BUILD_LINK" + fi + + # JFrog CLI does not allow colon characters in the properties, so we need to replace them with underscores in the build logs that are used to generate the properties for the upload step + sed -i 's/:/_/g' *.build + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: build-artifacts + path: build/ + upload-to-s3: needs: pkg-release runs-on: 'lecore-prd-u2404-arm64-xlrg-od-ephem' @@ -285,3 +297,14 @@ jobs: s3_bucket: qli-prd-lecore-gh-artifacts path: build destination: ${{ env.S3_BUCKET_PATH }} + + - name: Notify qcom-distro-images of new release via repository dispatch + uses: peter-evans/repository-dispatch@v3 + with: + token: ${{secrets.TOKEN}} + repository: qualcomm-linux/qcom-distro-images + event-type: pkg-repo-release + client-payload: >- + { + "artifact_path":"${{ env.S3_BUCKET_PATH }}" + }