Как сделать элемент матрицы действий GitHub условным?

У меня есть рабочий процесс, который использует 'strategy' = 'matrix' вместе со списком конкретных конфигураций для сборки.

Вот мой рабочий файл:

#
# build-N-test-v2.1-Dev and build-N-test-v2.1-Release are neary
# identical, but a few tests are commented out (to not needlessly stress CI system)
# for v2.1-Dev builds
#
# NOTE: I've tried many tricks - none which seem to work - to get this working on one file with one
# workflow and tests
#     https://github.community/t/what-is-the-correct-if-condition-syntax-for-checking-matrix-os-version/16221
#     https://github.community/t/how-to-conditionally-include-exclude-items-in-matrix-eg-based-on-branch/16853
#
# but none seem to work
#

name: build-N-test-v2.1-Dev

on:
  push:
    branches:
      - v2.1-Dev
      #- v2.1-Release
  workflow_dispatch:
    inputs:
      ignored:
        description: "ignored"
        required: false
        default: ""

## NB: JOBS section IDENTICAL between v2.1-Dev and 2.1-Release files EXCEPT that on v2.1-Dev file
## comment out all entries marked with includeInDevBranchBuilds: false
jobs:
  build-n-test-Linux:
    runs-on: ${{ matrix.runs_on }}
    strategy:
      #
      # Configuration notes
      #   o --debug-symbols false to reduce build disk size (and we aren't debugging anyhow) in many debug configurations
      #
      matrix:
        include:
          # ## SADLY: Container operations are only supported on Linux runners
          # - displayTargetName: windows-DBG
          #   os: windows
          #   compiler: g++-8
          #   runs_on: windows-latest
          #   container_image: sophistsolutionsinc/stroika-buildvm-windows-cygwin-vs2k19
          #   cpp_version: c++17
          #   config_name: Debug
          #   extra_config_args: --apply-default-debug-flags --trace2file enable

          ## centos 8
          - displayTargetName: centos-8
            os: unix
            compiler: g++
            runs_on: ubuntu-latest
            container_image: sophistsolutionsinc/stroika-buildvm-centos-8-small
            cpp_version: c++17
            config_name: Release
            extra_config_args: --apply-default-release-flags --trace2file enable
            includeInDevBranchBuilds: true

          ## ubuntu 18.04
          - displayTargetName: ubuntu-18.04-g++-8 (Debug)
            os: unix
            compiler: g++-8
            runs_on: ubuntu-latest
            container_image: sophistsolutionsinc/stroika-buildvm-ubuntu1804-regression-tests
            cpp_version: c++17
            config_name: Debug
            extra_config_args: --apply-default-debug-flags --trace2file enable --debug-symbols false
            includeInDevBranchBuilds: true

          - displayTargetName: ubuntu-18.04-cross-compile-raspberrypi (Debug)
            os: unix
            compiler: g++-8
            runs_on: ubuntu-latest
            container_image: sophistsolutionsinc/stroika-buildvm-ubuntu1804-regression-tests
            cpp_version: c++17
            config_name: Debug
            extra_config_args: --apply-default-release-flags --trace2file enable --compiler-driver arm-linux-gnueabihf-g++-8 --cross-compiling true
            includeInDevBranchBuilds: true

          # ubuntu 20.04
          # - displayTargetName: ubuntu-20.04-g++-9 (Debug)
          #   os: unix
          #   compiler: g++-9
          #   runs_on: ubuntu-latest
          #   container_image: sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests
          #   cpp_version: c++17
          #   config_name: Debug
          #   extra_config_args: --apply-default-debug-flags --trace2file enable --debug-symbols false
          #   includeInDevBranchBuilds: false

          # - displayTargetName: ubuntu-20.04-g++-10 (Debug)
          #   os: unix
          #   compiler: g++-10
          #   runs_on: ubuntu-latest
          #   container_image: sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests
          #   cpp_version: c++17
          #   config_name: Debug
          #   extra_config_args: --apply-default-debug-flags --trace2file enable --debug-symbols false
          #   includeInDevBranchBuilds: false

          - displayTargetName: ubuntu-20.04-g++-10
            os: unix
            compiler: g++-10
            runs_on: ubuntu-latest
            container_image: sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests
            cpp_version: c++17
            config_name: Release
            extra_config_args: --apply-default-release-flags --trace2file enable
            includeInDevBranchBuilds: true

          # - displayTargetName: ubuntu-20.04-g++-10-c++2a
          #   os: unix
          #   compiler: g++-10
          #   runs_on: ubuntu-latest
          #   container_image: sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests
          #   cpp_version: c++2a
          #   config_name: Release
          #   extra_config_args: --apply-default-release-flags --trace2file enable
          #   includeInDevBranchBuilds: false

          # - displayTargetName: ubuntu-20.04-clang++-10
          #   os: unix
          #   compiler: clang++-10
          #   runs_on: ubuntu-latest
          #   container_image: sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests
          #   cpp_version: c++17
          #   config_name: Release
          #   extra_config_args: --apply-default-release-flags --trace2file enable
          #   includeInDevBranchBuilds: false

    ### ATTEMPT TO COMPRESS 2 workflow files into one, but so far not working
    ### SEE
    ### https://stackoverflow.com/questions/65384420/how-to-make-a-github-action-matrix-element-conditional/65385385#65385385
    ###
    #if: github.ref == 'refs/heads/v2.1-Release' || matrix.includeInDevBranchBuilds
    env:
      # vm has 2 virtual CPUs, but 8GB ram, so jobs=5 (empirical), and QUICK_BUILD avoids some internal testing
      MAKEFLAGS: "--jobs=3 QUICK_BUILD=1"
    container: ${{ matrix.container_image }}
    steps:
      - uses: actions/checkout@v2
      - name: Build System Info
        if: ${{ matrix.os=='unix' }}
        run: |
          lsb_release -d 2>/dev/null || true
          echo "CWD = " `pwd`
          echo "nproc = " `nproc`
          grep "model name" /proc/cpuinfo | head -1
          grep processor /proc/cpuinfo | wc -l
          grep MemTotal /proc/meminfo
          df -h
      - name: Build System Info (Windows)
        if: ${{ matrix.os=='windows' }}
        run: |
          echo "CWD = " `pwd`
          df -h
      - name: Configure ${{ matrix.config_name }}
        run: |
          ./configure ${{ matrix.config_name }} --compiler-driver ${{ matrix.compiler }} ${{ matrix.extra_config_args }} --cppstd-version ${{ matrix.cpp_version }}
          cat ConfigurationFiles/${{ matrix.config_name }}.xml
      # Break out third-party-components to do clean so we dont run out of disk space, and break out TPC AND library
      # to show the summary time for each part
      - name: Make third-party-components
        run: |
          make third-party-components
          make clean
      - name: Make libraries
        run: make libraries
      - name: Make all
        run: make all
      - name: Run Tests
        run: make run-tests
      - name: Archive Samples Results
        uses: actions/upload-artifact@v2
        with:
          name: Sample apps (${{ matrix.displayTargetName }})
          path: |
            Builds/${{ matrix.config_name }}/Samples-*
      - name: Archive Log Results
        uses: actions/upload-artifact@v2
        with:
          name: Log Data (${{ matrix.displayTargetName }})
          path: |
            Builds/${{ matrix.config_name }}/PerformanceDump.txt
            /tmp/Trace*.txt

  build-n-test-MacOS:
    runs-on: ${{ matrix.runs_on }}
    strategy:
      matrix:
        # Add to extra_config_args for build speed: --Xerces no --OpenSSL no --lzma no --boost no
        include:
          - displayTargetName: MacOS-Debug
            os: macos-10.15
            runs_on: macos-10.15
            config_name: Debug
            extra_config_args: --apply-default-debug-flags --trace2file enable
            includeInDevBranchBuilds: true
          # - displayTargetName: MacOS
          #   os: macos-10.15
          #   runs_on: macos-10.15
          #   config_name: Release
          #   extra_config_args: --apply-default-release-flags --trace2file enable
          #   includeInDevBranchBuilds: false
    env:
      # vm has 2 virtual CPUs, but 8GB ram, so jobs=5 (empirical), and QUICK_BUILD avoids some internal testing
      MAKEFLAGS: "--jobs=3 QUICK_BUILD=1"
    steps:
      - uses: actions/checkout@v2
      - name: Build System Info
        run: |
          echo "CWD: `pwd`"
          df -h
          system_profiler SPSoftwareDataType
          sw_vers
      # If we had docker ability, most of these would be built into a docker file
      - name: Install Basic Build requirements
        run: |
          brew install gnu-sed
          brew install p7zip
          brew install automake
          make install-realpath
      - name: Configure
        run: |
          ./configure ${{ matrix.config_name }} ${{ matrix.extra_config_args }}
          cat ConfigurationFiles/${{ matrix.config_name }}.xml
      - name: Build third-party-components
        run: |
          make third-party-components
          make clean
      - name: Build Library
        run: |
          make libraries
      - name: Build All
        run: |
          make all
      - name: Run-Tests
        run: |
          make run-tests
      - name: Workaround GitHub-Actions-MacOS Issue with env.TMPDIR
        run: |
          mkdir /tmp/LOGS-ARCHIVE
          cp $TMPDIR/Trace*.txt /tmp/LOGS-ARCHIVE
      - name: DEBUG Workaround GitHub-Actions-MacOS Issue with env.TMPDIR
        run: |
          echo "TMPDIR=$TMPDIR"
          echo "TMPDIR using ENV.TMPDIR=${{ env.TMPDIR }}"
          # Just the echo line above shows empty, and then the ls line causes exit 1/failure
          #ls -l ${{ env.TMPDIR }}/Trace*.txt
          #if this gets fixed, then lose Workaround GitHub-Actions-MacOS, and directly reference ${{ env.TMPDIR }}/Trace*.txt in Archive Log Results
      - name: Build System Info
        run: |
          df -h
      - name: Archive Log Results
        uses: actions/upload-artifact@v2
        with:
          name: Log Results (${{ matrix.displayTargetName }})
          path: |
            Builds/${{ matrix.config_name }}/PerformanceDump.txt
            /tmp/LOGS-ARCHIVE
            #${{ env.TMPDIR }}/Trace*.txt
      - name: Archive Sample Results
        uses: actions/upload-artifact@v2
        with:
          name: Samples (${{ matrix.displayTargetName }})
          path: |
            Builds/${{ matrix.config_name }}/Samples-*

  build-n-test-Windows:
    runs-on: ${{ matrix.runs_on }}
    strategy:
      matrix:
        # Add to extra_config_args for build speed: --Xerces no --OpenSSL no --lzma no --boost no
        include:
          - displayTargetName: windows-x86-Debug
            os: windows
            runs_on: windows-latest
            container_image: sophistsolutionsinc/stroika-buildvm-windows-cygwin-vs2k19
            config_name: Debug
            extra_config_args: --arch x86 --apply-default-debug-flags --trace2file enable
            includeInDevBranchBuilds: true
          # - displayTargetName: windows-x86-Release
          #   os: windows
          #   runs_on: windows-latest
          #   container_image: sophistsolutionsinc/stroika-buildvm-windows-cygwin-vs2k19
          #   config_name: Release
          #   extra_config_args: --arch x86 --apply-default-release-flags --trace2file enable
          #   includeInDevBranchBuilds: false
          # - displayTargetName: windows-x86_64-Debug
          #   os: windows
          #   runs_on: windows-latest
          #   container_image: sophistsolutionsinc/stroika-buildvm-windows-cygwin-vs2k19
          #   config_name: Debug
          #   extra_config_args: --arch x86_64 --apply-default-debug-flags --trace2file enable
          #   includeInDevBranchBuilds: false
          # - displayTargetName: windows-x86_64-Release
          #   os: windows
          #   runs_on: windows-latest
          #   container_image: sophistsolutionsinc/stroika-buildvm-windows-cygwin-vs2k19
          #   config_name: Release
          #   extra_config_args: --arch x86 --apply-default-release-flags --trace2file enable
          #   includeInDevBranchBuilds: false
    env:
      # vm has 2 virtual CPUs, but 8GB ram, so jobs=5 (empirical), and QUICK_BUILD avoids some internal testing
      MAKEFLAGS: "--jobs=3 QUICK_BUILD=1"
      ARTIFACTS_DIR: "c:/Artifacts/"
    steps:
      - uses: actions/checkout@v2
      # https://stackoverflow.com/questions/58033366/how-to-get-current-branch-within-github-actions
      - name: Extract branch name
        shell: bash
        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
        id: extract_branch
      - name: Build System Info
        shell: "bash"
        run: |
          echo "CWD: `pwd`"
          df -h
          systeminfo
          echo NUMBER_OF_PROCESSORS=$NUMBER_OF_PROCESSORS
      - name: docker pull ${{ matrix.container_image }}
        run: docker pull ${{ matrix.container_image }}
      - name: Start docker build environment
        run: |
          docker run --tty --memory 5G --cpus 2 --storage-opt 'size=50GB' --detach --name buildContainer ${{ matrix.container_image }}
      - name: Print Info about docker system
        shell: "bash"
        run: |
          docker ps -a
          docker exec buildContainer systeminfo
          docker exec buildContainer df -h
      - name: Git Checkout
        shell: "bash"
        run: |
          docker exec buildContainer sh -c "git clone https://github.com/SophistSolutions/Stroika.git && cd Stroika && git checkout ${{ steps.extract_branch.outputs.branch }}"
      - name: Configure
        shell: "bash"
        run: |
          docker exec --workdir c:/Stroika buildContainer sh -c "./configure ${{ matrix.config_name }} ${{ matrix.extra_config_args }}"
          docker exec --workdir c:/Stroika buildContainer cat ConfigurationFiles/${{ matrix.config_name }}.xml
      - name: Build
        shell: "bash"
        run: |
          docker exec --workdir c:/Stroika --env MAKEFLAGS = "$MAKEFLAGS" buildContainer make all
      - name: Run-Tests
        shell: "bash"
        run: |
          docker exec --workdir c:/Stroika --env MAKEFLAGS = "$MAKEFLAGS" buildContainer make run-tests
      - name: Build System Info
        shell: "bash"
        run: |
          df -h
          docker exec buildContainer df -h
      - name: Copy Build Artifacts
        shell: "bash"
        # due to flaws in docker (windows must stop) - and cp no wildcards
        run: |
          docker exec --workdir c:/Stroika buildContainer bash -c 'mkdir TRACE_LOGS && cp $TEMP/Trace*.txt TRACE_LOGS/'
          docker stop buildContainer
          docker cp buildContainer:Stroika/Builds/${{ matrix.config_name }}/ $ARTIFACTS_DIR 2> /dev/null
          docker cp buildContainer:Stroika/TRACE_LOGS $ARTIFACTS_DIR 2> /dev/null
          rm -rf $ARTIFACTS_DIR/{ThirdPartyComponents,Tests,*.lib}
      - name: Archive Log Results
        uses: actions/upload-artifact@v2
        with:
          name: Log Results (${{ matrix.displayTargetName }})
          path: |
            ${{ env.ARTIFACTS_DIR }}PerformanceDump.txt
            ${{ env.ARTIFACTS_DIR }}TRACE_LOGS
      - name: Archive Sample Results
        uses: actions/upload-artifact@v2
        with:
          name: Samples (${{ matrix.displayTargetName }})
          path: |
            ${{ env.ARTIFACTS_DIR }}Samples-*

Однако я хотел бы создавать некоторые конфигурации только тогда, когда ветка v2.1-Release. То есть, по большей части, просто создайте одну или две конфигурации, но при выпуске создайте еще кучу.

Я добился этого, клонировав сценарий (рабочий процесс), переименовав несколько вещей и закомментировав их, но было бы неплохо, если бы этот механизм работал с матричными элементами.

Я понимаю, что есть функция if, которую можно добавить к каждому шагу, но это создаст массу рабочих мест с отключенными шагами. Чего я хочу, так это вообще не запускать эти задания для каждого матричного элемента, в котором часть if оценивается как ложная.

Редкие достижения на Github ✨
Редкие достижения на Github ✨
Редкая коллекция доступна в профиле на GitHub ✨
34
0
19 866
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

TLDR: вы можете делать то, что хотите, с помощью одного рабочего процесса, фильтруя конфигурации, которые вы хотите использовать в предыдущем задании/этапе сборки, и используя результат этой фильтрации в качестве значения матрицы в своем задании build-n-test.


Более длинная версия:

Вы можете создать job (т. е. build-n-test), где значение strategy.matrix отличается в зависимости от некоторых критериев, установив значение strategy.matrix на десериализованное output предыдущего задания (т. е. matrix_prep). Эта предыдущая работа будет нести ответственность за построение значения matrix в соответствии с вашими пользовательскими критериями. Следующий yaml демонстрирует это (копия была включена позже с добавленными комментариями для объяснения):

name: Configurable Build Matrix

on: push
jobs:
  matrix_prep:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
    - name: Check out code into the Go module directory
      uses: actions/checkout@v2
    - id: set-matrix
      run: |
        branchName=$(echo '${{ github.ref }}' | sed 's,refs/heads/,,g')  
        matrix=$(jq --arg branchName "$branchName" 'map( 
            . | select((.runOn==$branchName) or (.runOn= = "always"))
        )' matrix_includes.json)                
        echo "matrix = {\"include\":$(echo $matrix)}" >> $GITHUB_OUTPUT
  build-n-test:
    needs: matrix_prep
    runs-on: ${{ matrix.runs_on }}
    strategy:
      matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
    steps:    
    - run: echo "Hello ${{ matrix.someValue }}"

Содержимое файла matrix_includes.json, используемого в задаче set-matrix, можно найти после этого абзаца. Чтобы увидеть, как будет выглядеть конфигурация матрицы из вопроса в формате JSON, посмотрите внизу этого ответа. Я пошел по пути создания файла JSON отдельно от самого определения рабочего процесса, потому что обнаружил, что включение необработанного JSON в сам рабочий процесс было очень запутанным (особенно если файл JSON был большим).

[
    {
        "runs_on":"ubuntu-16.04",
        "someValue":"Foo",
        "runOn":"always"
    },
    {
        "runs_on":"ubuntu-18.04",
        "someValue":"Bar",
        "runOn":"v2.1-Release"
    },
    {
        "runs_on":"ubuntu-20.04",
        "someValue":"Hello again",
        "runOn":"v2.1-Release"
    }
]

Используя приведенную выше настройку, одна конфигурация будет включена для всех сборок, а две будут включены только в том случае, если имя ветки соответствует v2.1-Release. С некоторыми изменениями в параметрах sed и jq в файле рабочего процесса ограничения на имена ветвей могут быть ослаблены, чтобы вы могли запускать конфигурации для всех ветвей, включающих -Release (а не только для одной ветви). Я могу включить это в этот ответ, если есть интерес (поскольку это не обязательно соответствует вашему текущему вопросу).

set-matrix Объяснение работы

Что касается задачи set-matrix, пожалуйста, обратитесь к следующим примечаниям:

# ${{ github.ref }} returns the full git ref. As such, 'refs/heads/` 
# should be stripped for easier future use.
branchName=$(echo '${{ github.ref }}' | sed 's,refs/heads/,,g')  
# Use jq to read in a json file that represents the matrix configuration. Each
# block has a 'runOn' property. The jq filter is setup to only output items that 
# are set to 'always' or that have a branch name that matches the current branch.
matrix=$(jq --arg branchName "$branchName" 'map(
  . | select((.runOn==$branchName) or (.runOn= = "always")) 
)' matrix_includes.json)        
# This 'echo' uses a special syntax so that the output of this job 
# is set correctly.
echo "matrix = {\"include\":$(echo $matrix)}" >> $GITHUB_OUTPUT

Объяснение рабочего процесса

Следующее содержимое yaml должно быть таким же, как и выше, с некоторыми дополнительными комментариями, которые помогут объяснить ситуацию:

name: Configurable Build Matrix
on: push
jobs:
  matrix_prep:
    # Using a separate job and agent so as to be able to use tools 
    # like 'sed' and 'jq'.
    runs-on: ubuntu-latest
    # Defining outputs of a job allows for easier consumption and use.
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
    # Checking out code as the set-matrix step utilizes a 
    # file named matrix_includes.json.
    - name: Check out code into the Go module directory
      uses: actions/checkout@v2
    # This step is explained more in a following section
    - id: set-matrix
      run: |
        branchName=$(echo '${{ github.ref }}' | sed 's,refs/heads/,,g')  
        matrix=$(jq --arg branchName "$branchName" 'map(
          . | select((.runOn==$branchName) or (.runOn= = "always")) 
        )' matrix_includes.json)                
        echo "matrix = {\"include\":$(echo $matrix)}" >> $GITHUB_OUTPUT
  build-n-test:
    # By stating 'needs' here, the output of 'matrix_prep' is 
    # available to this job.
    needs: matrix_prep
    runs-on: ${{ matrix.runs_on }}
    strategy:
      # We need to convert the json string output into an object that the 
      # GitHub Workflow expects. Thankfully, the json-schema for Workflows 
      # allows 'matrix' to be set to an expression.
      matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
    steps:
    # Output a configuration specific value as proof and as a sanity check
    - run: echo "Hello ${{ matrix.someValue }}"

Демонстрация

Я собрал два файла для этой демонстрации:

Следующие два снимка экрана относятся к запускам в разных ветвях с использованием одного и того же определения рабочего процесса. Обратите внимание, что количество заданий build-n-test различается между двумя:

Сборка для основной ветки Сборка для ветки v2.1-Release

Это связано с тем, что первая сборка происходит на ветке main, а вторая — на ветке v2.1-Release. Как видно из включенного файла matrix_includes.json выше, этого следовало ожидать, поскольку две конфигурации настроены на запуск только тогда, когда ветка v2.1-Release, и только одна конфигурация настроена на постоянное выполнение.

Дальнейшие детали

Фильтрация конфигурации матрицы

Фильтрация осуществляется с помощью jq для выбора объектов из массива json, у которых либо значение runOn установлено на always, либо которые соответствуют текущему branchName. Это небольшая поправка к вашей логике, о которой я упоминал ранее: вместо того, чтобы говорить includeInDevBranchBuilds, я использую runOn, поскольку в этом конкретном примере это работает лучше.

Название филиала

Шаг set-matrix использует набор значений из предыдущей строки: branchName=$(echo '${{ github.ref }}' | sed 's,refs/heads/.*-,,g'). Эта строка удалит refs/heads/ из ссылки на ветку и сохранит результат в значении branchName. Например, если ваша ветвь 2.1-Release, branchName будет установлена ​​на 2.1-Release, а фильтр из более раннего будет соответствовать всем объектам, которые имеют "runOn":"2.1-Release" или "runOn":"always".

Файл JSON

Файл JSON был создан для имитации содержимого оператора includes из рабочего процесса, который вы связали. JSON используется, поскольку действия GitHub имеют встроенные функции JSON. В качестве примера ниже приведен мой вариант преобразования вашего раздела matrix:include в JSON. Обратите внимание, что я изменил includeInDevBranchBuilds на runOn со значениями, установленными либо на always, либо на v2.1-Release.

[
   {
      "displayTargetName": "centos-8",
      "os": "unix",
      "compiler": "g++",
      "runs_on": "ubuntu-latest",
      "container_image": "sophistsolutionsinc/stroika-buildvm-centos-8-small",
      "cpp_version": "c++17",
      "config_name": "Release",
      "extra_config_args": "--apply-default-release-flags --trace2file enable",
      "runOn": "always"
   },
   {
      "displayTargetName": "ubuntu-18.04-g++-8 (Debug)",
      "os": "unix",
      "compiler": "g++-8",
      "runs_on": "ubuntu-latest",
      "container_image": 
        "sophistsolutionsinc/stroika-buildvm-ubuntu1804-regression-tests",
      "cpp_version": "c++17",
      "config_name": "Debug",
      "extra_config_args": "--apply-default-debug-flags --trace2file enable",
      "runOn": "always"
   },
   {
      "displayTargetName": "ubuntu-20.04-g++-9 (Debug)",
      "os": "unix",
      "compiler": "g++-9",
      "runs_on": "ubuntu-latest",
      "container_image": 
        "sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests",
      "cpp_version": "c++17",
      "config_name": "Debug",
      "extra_config_args": "--apply-default-debug-flags --trace2file enable",
      "runOn": "v2.1-Release"
   },
   {
      "displayTargetName": "ubuntu-20.04-g++-10 (Debug)",
      "os": "unix",
      "compiler": "g++-10",
      "runs_on": "ubuntu-latest",
      "container_image": 
        "sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests",
      "cpp_version": "c++17",
      "config_name": "Debug",
      "extra_config_args": "--apply-default-debug-flags --trace2file enable",
      "runOn": "v2.1-Release"
   },
   {
      "displayTargetName": "ubuntu-20.04-g++-10",
      "os": "unix",
      "compiler": "g++-10",
      "runs_on": "ubuntu-latest",
      "container_image": 
        "sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests",
      "cpp_version": "c++17",
      "config_name": "Release",
      "extra_config_args": "--apply-default-release-flags --trace2file enable",
      "runOn": "always"
   },
   {
      "displayTargetName": "ubuntu-20.04-g++-10-c++2a",
      "os": "unix",
      "compiler": "g++-10",
      "runs_on": "ubuntu-latest",
      "container_image": 
        "sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests",
      "cpp_version": "c++2a",
      "config_name": "Release",
      "extra_config_args": "--apply-default-release-flags --trace2file enable",
      "runOn": "v2.1-Release"
   },
   {
      "displayTargetName": "ubuntu-20.04-clang++-10",
      "os": "unix",
      "compiler": "clang++-10",
      "runs_on": "ubuntu-latest",
      "container_image": 
         "sophistsolutionsinc/stroika-buildvm-ubuntu2004-regression-tests",
      "cpp_version": "c++17",
      "config_name": "Release",
      "extra_config_args": "--apply-default-release-flags --trace2file enable",
      "runOn": "v2.1-Release"
   }
]

@lewis, нет простого встроенного переключателя включения / выключения, подобного тому, что вы описываете для матричных сборок сегодня (29 декабря 2020 г.). Однако вы можете добиться результата, который вы описываете, как показано выше. Если встроенная опция станет доступной, я свяжусь с этим ответом при добавлении.

JoshuaTheMiller 30.12.2020 06:04

это было НЕВЕРОЯТНО здорово! ответ (в том смысле, что вы были очень ясно о том, почему и как). К сожалению, ответ ужасно сложен. Я все еще не уверен, что стоит изменить мой текущий процесс (дублировать отладку в файл конфигурации выпуска и раскомментировать строки). Но возможно. ПОЖАЛУЙСТА, дайте мне знать, если github когда-либо решит это более прямолинейно (например, переключатель включения / выключения в каждом элементе матрицы).

lewis 06.01.2021 02:11

Может быть, последний \" здесь не нужен? echo ::set-output name=matrix::{\"include\":$(echo $matrix)}\"

Antonio Gamiz Delgado 21.05.2021 12:00

ооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооо Я даже не думал, что смогу использовать fromJson и передать динамическое значение в матрицу. Это просто изменило все.

basicdays 08.01.2022 01:32

@AntonioGamizDelgado Вы правы, последнее \n неверно (выяснилось после использования этих примеров для моего собственного рабочего процесса). Я отредактировал ответ и удалил его.

mkurz 01.05.2022 02:37

Добавление еще одного ответа, так как в этом используются настраиваемые действия вместо встроенных сценариев оболочки. Отказ от ответственности: я являюсь сопровождающим одного из действий (спасибо за вдохновение).


Используя два дополнительных действия,

Вы можете добиться того же эффекта, что и пользовательский сценарий оболочки в моем другом ответе, но, возможно, более чистым способом:

.github/рабочие процессы/sample.yml

name: Configurable Build Matrix

on: push
jobs:
  matrix_prep:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - uses: actions/checkout@v2
      - uses: nelonoel/[email protected]
      - id: set-matrix
        uses: JoshuaTheMiller/[email protected]       
        with:          
          filter: '[?runOn==`${{ env.BRANCH_NAME }}` || runOn==`always`]'
  build-n-test:
    needs: matrix_prep
    runs-on: ${{ matrix.runs_on }}
    strategy:
      matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
    steps:
    - run: echo "Hello ${{ matrix.someValue }}"

.github/рабочие процессы/matrix_includes.json

[
    {
        "runs_on":"ubuntu-16.04",
        "someValue":"Foo",
        "runOn":"always"
    },
    {
        "runs_on":"ubuntu-18.04",
        "someValue":"Bar",
        "runOn":"v2.1-Release"
    },
    {
        "runs_on":"ubuntu-20.04",
        "someValue":"Hello again",
        "runOn":"v2.1-Release"
    }
]

оба файла можно найти в репозитории Action

Примечания

Я получаю эту ошибку из вашего решения: рабочий процесс недействителен. .github/workflows/release.yml (строка: 22, столбец: 15): ожидаемый формат {org}/{repo}[/path]@ref. Фактическая входная строка «JoshuaTheMiller/conditional-build-matrix» имеет неверный формат.

Fernando Rojo 09.07.2021 21:58

@FernandoRojo, не могли бы вы предоставить ссылку на свой репозиторий и/или открыть проблему в GitHub Action, если считаете, что проблема существует? В качестве быстрой проверки работоспособности я повторно запустил образец сборки, демонстрирующий этот ответ, и он работал правильно: github.com/JoshuaTheMiller/conditional-build-matrix/actions/‌​…

JoshuaTheMiller 12.07.2021 17:59

Я думаю, это потому, что вы использовали локальное действие, а не импортировали его из отдельного репо. Попробуйте создать отдельный репозиторий, который импортирует ваши действия, и вы поймете, что я имею в виду.

Fernando Rojo 11.08.2021 02:16

@FernandoRojo Я запустил это из другого репо в качестве проверки работоспособности, и сборка завершилась успешно. Не могли бы вы поделиться ссылкой на вашу сборку, которая терпит неудачу?

JoshuaTheMiller 11.08.2021 20:16

Я только что обновил этот ответ, включив в него версию моего действия (@0.0.1), поскольку раньше оно отсутствовало в этом ответе. Может ли это быть корнем проблемы, которую вы видите?

JoshuaTheMiller 11.08.2021 20:20

Я нашел этот пост, и он был очень полезным. Хотя это гораздо сложнее, чем вариант использования, который у меня был.

Это побудило меня изучить другие решения, и я придумал альтернативный ответ, который работает для более простых случаев использования, когда вы просто хотите исключить одно измерение матрицы для определенных условий.

Примеры будут:

  • Включите apple, если текущее действие выполняется на ветке main
  • Включить banana в сборки без PR ИЛИ в сборки PR, когда метка BUILD-BANANA применяется к PR
strategy:
  matrix:
    fruits:
      - apple
      - banana
    exclude:
      - fruits: ${{ github.ref == 'refs/heads/main' && 'dummy' || 'apple' }}
      - fruits: ${{ (github.event_name != 'pull_request' || (github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'BUILD-BANANA'))) && 'dummy' || 'banana' }}

Строка 'dummy' назначается исключенным фруктам, когда фрукты не следует исключать.

Это сработало для меня... но мне пришлось изменить && '' || 'apple' на && 'dummy' || 'apple'. Поскольку '' является «ложным», это приводит к тому, что apple всегда исключается.

huntharo 02.01.2023 05:58

Я ПОНИМАЮ, что есть функция «если», которую можно добавить к каждому шагу, но это создаст массу заданий с отключенными шагами. Что я хочу, так это просто не запускать эти задания для каждого матричного элемента, в котором часть if оценивается как false.

С многоразовыми рабочими процессами мы можем полностью пропустить (повторно используемые) задания (по сравнению с каждым шагом), просто добавив одно условие к (повторно используемому) заданию/передав флаг в качестве входных данных. Не идеальный вариант, поскольку мы по-прежнему получаем пропущенные задания в отчетах, но довольно серьезный недостаток по сравнению с обусловливанием каждого шага задания.

матрица-workflow.yml:

jobs:
  build:
    strategy:
      matrix:
        build-config:
          - foo: 'bar'
            if: ${{ xxx }}
          - foo: 'baz'
            if: ${{ yyy }}
    uses: ./.github/workflows/reusable-workflow.yml
    with:
      if: ${{ matrix.build-config.if }}
      foo: ${{ matrix.build-config.foo }}

многоразовый-workflow.yml:

on:
  workflow_call:
    inputs:
      if:
        description: 'Whether to run this job'
        required: false
        default: true
        type: boolean
      foo:
        required: true
        type: string
jobs:
  reusable-build:
    if: ${{ inputs.if }}
...

Пример пропущенного задания в отчетах:

Это фантастика! Ну, это не необходимость «еще одного уровня косвенности», но это проблема GitHub Actions в целом. Я нашел это, потому что искал способ иметь матрицу заданий, которые все «пропускают», если знают, что им ничего не нужно делать, но которые также могут быть перечислены как «обязательные проверки» в защите ветвей. Если вы установите пропуск на уровне матрицы, проверки защиты ветвления никогда не будут выполнены. Выполнение этого в отдельных работах работает нормально. Небольшое улучшение: 'if' в задании повторно используемого рабочего процесса не нуждается в "${{ }}", так как это контекст выражения.

Kevin P. Fleming 09.01.2023 16:36

Чего большинство людей не понимают, так это того, что матрицы, например. матричные конфигурации с включением гораздо более удобны и сложны, чем обычные матрицы. Например, в Terraform это важно,

Добавление задания № 0 только для динамического создания «включаемых» матриц является хромым и будет портить внешний вид — это разумно только в том случае, если у вас есть 1 канал, который выполняет все окружения, и 1000 различных виртуальных машин / K8S на основе хромого ввода.

Что нам нужно, так это автоматически исключить включение матричной конфигурации, если есть только один корреспондент env: dev, если у нас есть только «dev» в списке envs, мы, очевидно, хотим пропустить все остальные, но все же github имеет лучшие функции канала.

Другие вопросы по теме