From 288f53c3a6376369fc8834987afe9457939a09b3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 29 Nov 2021 13:19:28 -0600 Subject: [PATCH 001/130] Updated runs-on to self-hosted,. --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index ef40d5c6f93a..738ecb585bfc 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -40,7 +40,7 @@ jobs: check_gcp_variables: timeout-minutes: 5 name: "Check GCP variables" - runs-on: ubuntu-latest + runs-on: self-hosted outputs: gcp-variables-set: ${{ steps.check_gcp_variables.outputs.gcp-variables-set }} steps: From a48a7e53776635dbf9527354702e0be7392d7799 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 29 Nov 2021 13:35:40 -0600 Subject: [PATCH 002/130] Updated runs-on jobs to self-hosted. --- .github/workflows/build_wheels.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 738ecb585bfc..459a397f5eb6 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -57,7 +57,7 @@ jobs: GCP_TESTING_BUCKET: "not-needed-here" build_source: - runs-on: ubuntu-latest + runs-on: self-hosted name: Build python source distribution outputs: is_rc: ${{ steps.is_rc.outputs.is_rc }} @@ -166,7 +166,7 @@ jobs: needs: - build_source - check_gcp_variables - runs-on: ubuntu-latest + runs-on: self-hosted if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' steps: - name: Authenticate on GCP @@ -182,7 +182,7 @@ jobs: needs: - prepare_gcs - check_gcp_variables - runs-on: ubuntu-latest + runs-on: self-hosted if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' steps: - name: Download compressed sources from artifacts @@ -203,7 +203,8 @@ jobs: needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} - runs-on: ${{ matrix.os_python.os }} + runs-on: self-hosted + container: ${{ matrix.os_python.os }} strategy: matrix: os_python: [ @@ -286,7 +287,8 @@ jobs: needs: - build_wheels - check_gcp_variables - runs-on: ubuntu-latest + runs-on: self-hosted + container: ${{ matrix.os }} if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: @@ -330,7 +332,7 @@ jobs: needs: - upload_wheels_to_gcs - check_gcp_variables - runs-on: ubuntu-latest + runs-on: self-hosted if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' steps: - name: Authenticate on GCP @@ -346,7 +348,7 @@ jobs: needs: - build_source - build_wheels - runs-on: ubuntu-latest + runs-on: self-hosted timeout-minutes: 60 if: github.repository_owner == 'apache' && github.event_name == 'schedule' steps: From 6245235ef9276cc07dcd648441724f09511e36bb Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 29 Nov 2021 13:54:10 -0600 Subject: [PATCH 003/130] Updated runs-on matrix --- .github/workflows/build_wheels.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 459a397f5eb6..33419e7a6625 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,8 +203,7 @@ jobs: needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} - runs-on: self-hosted - container: ${{ matrix.os_python.os }} + runs-on: [self-hosted, ${{ matrix.os_python.os }}] strategy: matrix: os_python: [ @@ -287,8 +286,7 @@ jobs: needs: - build_wheels - check_gcp_variables - runs-on: self-hosted - container: ${{ matrix.os }} + runs-on: [self-hosted, ${{ matrix.os }}] if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: From c636ff0eefc4dce6df4ce4d5b38a9195d469f0a3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 29 Nov 2021 17:04:56 -0600 Subject: [PATCH 004/130] Updated runs-on matrix, cache pip --- .github/workflows/build_wheels.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 33419e7a6625..6b7b2b0360e5 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -68,7 +68,8 @@ jobs: - name: Install python uses: actions/setup-python@v2 with: - python-version: 3.7 + python-version: '3.7' + cache: 'pip' - name: Get build dependencies working-directory: ./sdks/python run: python -m pip install -r build-requirements.txt @@ -203,7 +204,8 @@ jobs: needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} - runs-on: [self-hosted, ${{ matrix.os_python.os }}] + runs-on: self-hosted + container: ${{ matrix.os_python.os }} strategy: matrix: os_python: [ @@ -286,7 +288,8 @@ jobs: needs: - build_wheels - check_gcp_variables - runs-on: [self-hosted, ${{ matrix.os }}] + runs-on: self-hosted + container: ${{ matrix.os }} if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: From 23ae887b074a3108af8bd92b673f583c14daaec1 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 29 Nov 2021 17:16:42 -0600 Subject: [PATCH 005/130] added mkdir hostedtoolcache --- .github/workflows/build_wheels.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 6b7b2b0360e5..56f65b6d3384 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -65,11 +65,12 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v2 + - name: Set hosted tool cache + run: mkdir /Users/runner/hostedtoolcache && export AGENT_TOOLSDIRECTORY=/Users/runner/hostedtoolcache && chmod 777 /Users/runner/hostedtoolcache - name: Install python uses: actions/setup-python@v2 with: - python-version: '3.7' - cache: 'pip' + python-version: 3.7 - name: Get build dependencies working-directory: ./sdks/python run: python -m pip install -r build-requirements.txt From 385d5d88b046a517332cea6f3131df961dba5d7d Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 29 Nov 2021 17:26:43 -0600 Subject: [PATCH 006/130] commented mkdir hostedtoolcache --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 56f65b6d3384..c358ee3e39c0 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -66,7 +66,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Set hosted tool cache - run: mkdir /Users/runner/hostedtoolcache && export AGENT_TOOLSDIRECTORY=/Users/runner/hostedtoolcache && chmod 777 /Users/runner/hostedtoolcache + # run: sudo mkdir /Users/runner/hostedtoolcache && export AGENT_TOOLSDIRECTORY=/Users/runner/hostedtoolcache && sudo chmod 777 /Users/runner/hostedtoolcache - name: Install python uses: actions/setup-python@v2 with: From 5b432cbdca0ff31c8e3abbfb2ec0db90a4fdfb58 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 29 Nov 2021 17:27:30 -0600 Subject: [PATCH 007/130] removed mkdir hostedtoolcache --- .github/workflows/build_wheels.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index c358ee3e39c0..8e04d80e7c3d 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -66,7 +66,6 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Set hosted tool cache - # run: sudo mkdir /Users/runner/hostedtoolcache && export AGENT_TOOLSDIRECTORY=/Users/runner/hostedtoolcache && sudo chmod 777 /Users/runner/hostedtoolcache - name: Install python uses: actions/setup-python@v2 with: From 26f688725634f747cd7fb7b8af554b14a928ca34 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 29 Nov 2021 17:30:56 -0600 Subject: [PATCH 008/130] removed -name var --- .github/workflows/build_wheels.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 8e04d80e7c3d..459a397f5eb6 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -65,7 +65,6 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v2 - - name: Set hosted tool cache - name: Install python uses: actions/setup-python@v2 with: From b6ad39e79236a1e381b86a4ae5ac48f46761ea24 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 10:11:08 -0600 Subject: [PATCH 009/130] Updated runs-on matrix values --- .github/workflows/build_wheels.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 459a397f5eb6..a87447193d46 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,11 +203,11 @@ jobs: needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} - runs-on: self-hosted - container: ${{ matrix.os_python.os }} + runs-on: ${{ matrix.os_python.os }} strategy: matrix: os_python: [ + {"os": "self-hosted", "python": "cp36-* cp37-* cp38-*"}, {"os": "ubuntu-latest", "python": "cp36-* cp37-* cp38-*"}, {"os": "macos-latest", "python": "cp36-* cp37-* cp38-*"}, {"os": "windows-latest", "python": "cp36-* cp37-* cp38-*"}, @@ -287,12 +287,11 @@ jobs: needs: - build_wheels - check_gcp_variables - runs-on: self-hosted - container: ${{ matrix.os }} + runs-on: ${{ matrix.os }} if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: - os : [ubuntu-latest, macos-latest, windows-latest] + os : [self-hosted, ubuntu-latest, macos-latest, windows-latest] steps: - name: Download wheels from artifacts uses: actions/download-artifact@v2 From 01b36de5e085842536fad4a923d2058dc1124d2d Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 10:19:49 -0600 Subject: [PATCH 010/130] Added Install Docker step --- .github/workflows/build_wheels.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index a87447193d46..fcf13bd099f2 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -217,6 +217,8 @@ jobs: - os_python: {"os": "ubuntu-latest", "python": "cp36-* cp37-* cp38-*"} arch: aarch64 steps: + - name: Install Docker + run: sudo apt-get update && sudo apt-get install docker-ce docker-ce-cli containerd.io && sudo docker run hello-world - name: Download python source distribution from artifacts uses: actions/download-artifact@v2 with: From a5189e7846bcf1649f0d555cacf476a48c0bc0aa Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 10:28:59 -0600 Subject: [PATCH 011/130] Install apt-get --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index fcf13bd099f2..6ff74308c5a0 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -218,7 +218,7 @@ jobs: arch: aarch64 steps: - name: Install Docker - run: sudo apt-get update && sudo apt-get install docker-ce docker-ce-cli containerd.io && sudo docker run hello-world + run: sudo apt-get install -y && sudo apt-get install docker-ce docker-ce-cli containerd.io && sudo docker --version - name: Download python source distribution from artifacts uses: actions/download-artifact@v2 with: From 7513e480a867a2d41556b116855f0d85ffdfbaea Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 10:37:46 -0600 Subject: [PATCH 012/130] Updated docker installation --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 6ff74308c5a0..5a5534d04d43 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -218,7 +218,7 @@ jobs: arch: aarch64 steps: - name: Install Docker - run: sudo apt-get install -y && sudo apt-get install docker-ce docker-ce-cli containerd.io && sudo docker --version + run: sudo curl -fsSL https://get.docker.com -o get-docker.sh && sudo sh get-docker.sh && sudo docker --version - name: Download python source distribution from artifacts uses: actions/download-artifact@v2 with: From b520505c2c553d6f650502b1a79e1eb6e4985d45 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 10:49:08 -0600 Subject: [PATCH 013/130] Added CIBW_BEFORE_ALL_LINUX docker install --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 5a5534d04d43..f3821f6f4644 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -218,7 +218,6 @@ jobs: arch: aarch64 steps: - name: Install Docker - run: sudo curl -fsSL https://get.docker.com -o get-docker.sh && sudo sh get-docker.sh && sudo docker --version - name: Download python source distribution from artifacts uses: actions/download-artifact@v2 with: @@ -244,6 +243,7 @@ jobs: env: CIBW_BUILD: ${{ matrix.os_python.python }} CIBW_BEFORE_BUILD: pip install cython + CIBW_BEFORE_ALL_LINUX: sudo apt-get install -y && sudo apt-get install docker-ce docker-ce-cli containerd.io && sudo docker --version run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - name: install sha512sum on MacOS From 116e67ac39e2a8d7e5c630a58161271d6ede0776 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 10:50:06 -0600 Subject: [PATCH 014/130] Fixed format issue --- .github/workflows/build_wheels.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index f3821f6f4644..be404cc00b72 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -217,7 +217,6 @@ jobs: - os_python: {"os": "ubuntu-latest", "python": "cp36-* cp37-* cp38-*"} arch: aarch64 steps: - - name: Install Docker - name: Download python source distribution from artifacts uses: actions/download-artifact@v2 with: From 08553788d7cdb3d0ba35395fae08466b73baa93e Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 10:55:16 -0600 Subject: [PATCH 015/130] Removed sudo from CIBW_BEFORE_ALL_LINUX command --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index be404cc00b72..2bb62d22f575 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -242,7 +242,7 @@ jobs: env: CIBW_BUILD: ${{ matrix.os_python.python }} CIBW_BEFORE_BUILD: pip install cython - CIBW_BEFORE_ALL_LINUX: sudo apt-get install -y && sudo apt-get install docker-ce docker-ce-cli containerd.io && sudo docker --version + CIBW_BEFORE_ALL_LINUX: apt-get install -y && apt-get install docker-ce docker-ce-cli containerd.io && docker --version run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - name: install sha512sum on MacOS From d83e61434df4acdd780953ad4d6af65a9c2ade3d Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 12:54:15 -0600 Subject: [PATCH 016/130] Added version and yum to docker-ce --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 2bb62d22f575..d9e01f079c69 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -242,7 +242,7 @@ jobs: env: CIBW_BUILD: ${{ matrix.os_python.python }} CIBW_BEFORE_BUILD: pip install cython - CIBW_BEFORE_ALL_LINUX: apt-get install -y && apt-get install docker-ce docker-ce-cli containerd.io && docker --version + CIBW_BEFORE_ALL_LINUX: yum install -y yum-utils && yum install docker-ce-18.06.0 docker-ce-cli-18.06.0 containerd.io run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - name: install sha512sum on MacOS From dc81f4ff42f494d9b85c5984fae44eb46ba53af8 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 13:04:04 -0600 Subject: [PATCH 017/130] Updatrd CIBW_BEFORE_ALL_LINUX --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index d9e01f079c69..96566def6e46 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -242,7 +242,7 @@ jobs: env: CIBW_BUILD: ${{ matrix.os_python.python }} CIBW_BEFORE_BUILD: pip install cython - CIBW_BEFORE_ALL_LINUX: yum install -y yum-utils && yum install docker-ce-18.06.0 docker-ce-cli-18.06.0 containerd.io + CIBW_BEFORE_ALL_LINUX: apt-get install -y && apt-get install docker-ce-18.06.0 docker-ce-cli-18.06.0 containerd.io run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - name: install sha512sum on MacOS From 57e40a3eb655d137978747b82a159a957b69bdb6 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 13:09:08 -0600 Subject: [PATCH 018/130] Removed CIBW_BEFORE_ALL_LINUX --- .github/workflows/build_wheels.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 96566def6e46..a87447193d46 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -242,7 +242,6 @@ jobs: env: CIBW_BUILD: ${{ matrix.os_python.python }} CIBW_BEFORE_BUILD: pip install cython - CIBW_BEFORE_ALL_LINUX: apt-get install -y && apt-get install docker-ce-18.06.0 docker-ce-cli-18.06.0 containerd.io run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - name: install sha512sum on MacOS From aff96da592c0bd38df4a6218df5106a9c0782984 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 15:50:58 -0600 Subject: [PATCH 019/130] Removed matrix variable and added self-hosted instead. --- .github/workflows/build_wheels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index a87447193d46..8a80995fef47 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,7 +203,7 @@ jobs: needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} - runs-on: ${{ matrix.os_python.os }} + runs-on: [self-hosted] strategy: matrix: os_python: [ @@ -287,7 +287,7 @@ jobs: needs: - build_wheels - check_gcp_variables - runs-on: ${{ matrix.os }} + runs-on: [self-hosted] if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: From 306c35fae2ddcd3899a92a261497559011e3af9d Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 30 Nov 2021 16:03:32 -0600 Subject: [PATCH 020/130] Removed self-hosteed from matrix wheels --- .github/workflows/build_wheels.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 8a80995fef47..1c3e02bd8677 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -207,7 +207,6 @@ jobs: strategy: matrix: os_python: [ - {"os": "self-hosted", "python": "cp36-* cp37-* cp38-*"}, {"os": "ubuntu-latest", "python": "cp36-* cp37-* cp38-*"}, {"os": "macos-latest", "python": "cp36-* cp37-* cp38-*"}, {"os": "windows-latest", "python": "cp36-* cp37-* cp38-*"}, From 3e85be232803c2af9a54fdea410d3096286e6114 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 1 Dec 2021 12:11:10 -0600 Subject: [PATCH 021/130] Updated python_tests to runs-on self-hosted runner. --- .github/workflows/python_tests.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 7278b3aaa728..d8be734da204 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -41,7 +41,7 @@ jobs: check_gcp_variables: timeout-minutes: 5 name: "Check GCP variables" - runs-on: ubuntu-latest + runs-on: self-hosted outputs: gcp-variables-set: ${{ steps.check_gcp_variables.outputs.gcp-variables-set }} steps: @@ -66,7 +66,7 @@ jobs: ) needs: - check_gcp_variables - runs-on: ubuntu-latest + runs-on: self-hosted steps: - name: Checkout code uses: actions/checkout@v2 @@ -91,11 +91,11 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: ${{ matrix.os }} + runs-on: [self-hosted] strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [self-hosted, ubuntu-latest, macos-latest, windows-latest] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, @@ -135,11 +135,11 @@ jobs: python_wordcount_direct_runner: name: 'Python Wordcount Direct Runner' - runs-on: ${{ matrix.os }} + runs-on: [self-hosted] strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [self-hosted, ubuntu-latest, macos-latest, windows-latest] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -168,11 +168,11 @@ jobs: name: 'Python Wordcount Dataflow' needs: - build_python_sdk_source - runs-on: ${{ matrix.os }} + runs-on: [self-hosted] strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [self-hosted, ubuntu-latest, macos-latest, windows-latest] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved From b6b87ccc181e45e23a94eee9a9f96386b743b456 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 1 Dec 2021 12:36:25 -0600 Subject: [PATCH 022/130] Removed ubuntu,macos and windows from matrix for testing self-hosted only. --- .github/workflows/python_tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index d8be734da204..ba2a3972954d 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -95,7 +95,7 @@ jobs: strategy: fail-fast: false matrix: - os: [self-hosted, ubuntu-latest, macos-latest, windows-latest] + os: [self-hosted] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, @@ -139,7 +139,7 @@ jobs: strategy: fail-fast: false matrix: - os: [self-hosted, ubuntu-latest, macos-latest, windows-latest] + os: [self-hosted] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -172,7 +172,7 @@ jobs: strategy: fail-fast: false matrix: - os: [self-hosted, ubuntu-latest, macos-latest, windows-latest] + os: [self-hosted] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved From 30b4bfe0ad6c5902791cb6a0c06249f8a321dee9 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 1 Dec 2021 12:48:13 -0600 Subject: [PATCH 023/130] Included 'self' in Run test basic unix if condition. --- .github/workflows/python_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index ba2a3972954d..dc2573ed2123 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -119,7 +119,7 @@ jobs: - name: Install tox run: pip install tox - name: Run tests basic unix - if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') + if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'self') working-directory: ./sdks/python run: tox -c tox.ini -e ${{ matrix.params.tox_env }} - name: Run tests basic windows From 798a0ecb1f293e2d3738b3a99d0c7b5497a1dac6 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 1 Dec 2021 12:57:30 -0600 Subject: [PATCH 024/130] Testing py36 only in self-hosted runner. --- .github/workflows/python_tests.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index dc2573ed2123..bfe5a98028ad 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -97,9 +97,7 @@ jobs: matrix: os: [self-hosted] params: [ - {"py_ver": "3.6", "tox_env": "py36"}, - {"py_ver": "3.7", "tox_env": "py37"}, - {"py_ver": "3.8", "tox_env": "py38"}, + {"py_ver": "3.6", "tox_env": "py36"} ] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -140,7 +138,7 @@ jobs: fail-fast: false matrix: os: [self-hosted] - python: [3.6, 3.7, 3.8] + python: [3.6] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 @@ -173,7 +171,7 @@ jobs: fail-fast: false matrix: os: [self-hosted] - python: [3.6, 3.7, 3.8] + python: [3.6] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 From c7dccbb712609972a8cf326f873f278a878183d1 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 1 Dec 2021 13:43:13 -0600 Subject: [PATCH 025/130] Added ubuntu-latest in matrix --- .github/workflows/python_tests.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index bfe5a98028ad..1b2ff6aeeb9a 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,11 +91,11 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: [self-hosted] + runs-on: self-hosted strategy: fail-fast: false matrix: - os: [self-hosted] + os: [ubuntu-latest] params: [ {"py_ver": "3.6", "tox_env": "py36"} ] @@ -133,11 +133,11 @@ jobs: python_wordcount_direct_runner: name: 'Python Wordcount Direct Runner' - runs-on: [self-hosted] + runs-on: self-hosted strategy: fail-fast: false matrix: - os: [self-hosted] + os: [ubuntu-latest] python: [3.6] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -166,11 +166,11 @@ jobs: name: 'Python Wordcount Dataflow' needs: - build_python_sdk_source - runs-on: [self-hosted] + runs-on: self-hosted strategy: fail-fast: false matrix: - os: [self-hosted] + os: [ubuntu-latest] python: [3.6] exclude: # TODO remove exclusion after issue with protobuf is solved From f8bacc956af78dfd3b86f518f18a1c3d1600627a Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 1 Dec 2021 16:11:28 -0600 Subject: [PATCH 026/130] Testing with windows-latest os --- .github/workflows/python_tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 1b2ff6aeeb9a..b20f69092785 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -95,7 +95,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [windows-latest] params: [ {"py_ver": "3.6", "tox_env": "py36"} ] @@ -137,7 +137,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [windows-latest] python: [3.6] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -170,7 +170,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [windows-latest] python: [3.6] exclude: # TODO remove exclusion after issue with protobuf is solved From 0ed2b6c4f9c7f91d342f2443017d640970f2d1c3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 1 Dec 2021 17:28:16 -0600 Subject: [PATCH 027/130] Incremented tox nodes to 8 --- sdks/python/scripts/run_pytest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/python/scripts/run_pytest.sh b/sdks/python/scripts/run_pytest.sh index cd8b8b74c5dc..d30fe295fb59 100755 --- a/sdks/python/scripts/run_pytest.sh +++ b/sdks/python/scripts/run_pytest.sh @@ -37,7 +37,7 @@ fi # Run with pytest-xdist and without. pytest -o junit_suite_name=${envname} \ - --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 6 ${pytest_args} --pyargs ${posargs} + --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 8 ${pytest_args} --pyargs ${posargs} status1=$? pytest -o junit_suite_name=${envname}_no_xdist \ --junitxml=pytest_${envname}_no_xdist.xml -m 'no_xdist' ${pytest_args} --pyargs ${posargs} From 583efdc0ee0e1a5b868f49ce6467d4cc9da03b86 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 1 Dec 2021 17:31:25 -0600 Subject: [PATCH 028/130] runs-on ubuntu-latest --- .github/workflows/python_tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index b20f69092785..1b2ff6aeeb9a 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -95,7 +95,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-latest] + os: [ubuntu-latest] params: [ {"py_ver": "3.6", "tox_env": "py36"} ] @@ -137,7 +137,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-latest] + os: [ubuntu-latest] python: [3.6] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -170,7 +170,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-latest] + os: [ubuntu-latest] python: [3.6] exclude: # TODO remove exclusion after issue with protobuf is solved From f4997b5413c1fd20fbff0bc77a86a31abff07871 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 1 Dec 2021 17:56:48 -0600 Subject: [PATCH 029/130] Reduced tox nodes to 4 --- sdks/python/scripts/run_pytest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/python/scripts/run_pytest.sh b/sdks/python/scripts/run_pytest.sh index d30fe295fb59..fff73eab4f86 100755 --- a/sdks/python/scripts/run_pytest.sh +++ b/sdks/python/scripts/run_pytest.sh @@ -37,7 +37,7 @@ fi # Run with pytest-xdist and without. pytest -o junit_suite_name=${envname} \ - --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 8 ${pytest_args} --pyargs ${posargs} + --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 4 ${pytest_args} --pyargs ${posargs} status1=$? pytest -o junit_suite_name=${envname}_no_xdist \ --junitxml=pytest_${envname}_no_xdist.xml -m 'no_xdist' ${pytest_args} --pyargs ${posargs} From 6d8b7c3c23e5d9f562a555bdd03183d38da7af05 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 7 Dec 2021 16:36:18 -0600 Subject: [PATCH 030/130] Added Dockerfile, entrypoint and docker-compose file to create the self-hosted image and container. --- .../dockerized-gh_actions_runners/Dockerfile | 42 +++++++++++++++++++ .../docker-compose.yml | 10 +++++ .../entrypoint.sh | 41 ++++++++++++++++++ .../example.var.env | 3 ++ 4 files changed, 96 insertions(+) create mode 100644 .github/dockerized-gh_actions_runners/Dockerfile create mode 100644 .github/dockerized-gh_actions_runners/docker-compose.yml create mode 100644 .github/dockerized-gh_actions_runners/entrypoint.sh create mode 100644 .github/dockerized-gh_actions_runners/example.var.env diff --git a/.github/dockerized-gh_actions_runners/Dockerfile b/.github/dockerized-gh_actions_runners/Dockerfile new file mode 100644 index 000000000000..8072d038714c --- /dev/null +++ b/.github/dockerized-gh_actions_runners/Dockerfile @@ -0,0 +1,42 @@ +################################################################################ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ + +FROM ubuntu:20.04 + +ARG RUNNER_VERSION=2.285.1 + +RUN apt-get -yqq update && apt-get install -yqq curl sudo git jq unzip tar gnupg2 apt-transport-https ca-certificates +RUN apt-get install -yqq liblttng-ust0 libkrb5-3 zlib1g libssl1.1 +RUN DEBIAN_FRONTEND=noninteractive apt-get install -yqq libicu66 +RUN apt-get clean +RUN rm -rf /var/lib/apt/lists/* +RUN useradd -m actions && usermod -aG sudo actions && echo "%sudo ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers +USER actions +WORKDIR /home/actions + +RUN curl -O -L https://github.com/actions/runner/releases/download/v$RUNNER_VERSION/actions-runner-linux-x64-$RUNNER_VERSION.tar.gz +RUN tar xzf ./actions-runner-linux-x64-$RUNNER_VERSION.tar.gz + +COPY --chown=actions:actions entrypoint.sh ./entrypoint.sh + +RUN sudo chmod u+x ./entrypoint.sh +RUN curl -fsSL https://get.docker.com -o get-docker.sh +RUN sudo sh get-docker.sh + +VOLUME [ "/var/run/docker.sock:/var/run/docker.sock"] +ENTRYPOINT ["/home/actions/entrypoint.sh"] diff --git a/.github/dockerized-gh_actions_runners/docker-compose.yml b/.github/dockerized-gh_actions_runners/docker-compose.yml new file mode 100644 index 000000000000..db9768a4fd59 --- /dev/null +++ b/.github/dockerized-gh_actions_runners/docker-compose.yml @@ -0,0 +1,10 @@ +version: "3.0" +services: + runner: + build: . + entrypoint: ["/home/actions/entrypoint.sh"] + image: beam-ga:${TAG:-latest} + volumes: + - "/var/run/docker.sock:/var/run/docker.sock" + env_file: + - ./var.env \ No newline at end of file diff --git a/.github/dockerized-gh_actions_runners/entrypoint.sh b/.github/dockerized-gh_actions_runners/entrypoint.sh new file mode 100644 index 000000000000..f6830a26c96f --- /dev/null +++ b/.github/dockerized-gh_actions_runners/entrypoint.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +sudo chmod 666 /var/run/docker.sock + +registration_url="https://api.github.com/repos/$GITHUB_REPO/beam/actions/runners/registration-token" +echo "Requesting registration URL at '${registration_url}'" + +payload=$(curl -sX POST -H "Authorization: token $GITHUB_TOKEN" ${registration_url}) +RUNNER_TOKEN=$(echo $payload | jq '.token' --raw-output) +export RUNNER_TOKEN + +./config.sh \ + --name $(hostname) \ + --token ${RUNNER_TOKEN} \ + --url https://github.com/$GITHUB_REPO/beam \ + --work _work \ + --unattended \ + --replace + +remove() { + ./config.sh remove --unattended --token "${RUNNER_TOKEN}" +} +trap 'remove; exit 130' INT +trap 'remove; exit 143' TERM +./run.sh "$*" & +wait $! diff --git a/.github/dockerized-gh_actions_runners/example.var.env b/.github/dockerized-gh_actions_runners/example.var.env new file mode 100644 index 000000000000..0ee67cd4f47b --- /dev/null +++ b/.github/dockerized-gh_actions_runners/example.var.env @@ -0,0 +1,3 @@ +# var.env example, please create a var.env file with the corresponding values of the variables +GITHUB_TOKEN= +GITHUB_REPO= \ No newline at end of file From 7628139262ac280feae456da6b9635c216759b6a Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 9 Dec 2021 18:01:31 -0600 Subject: [PATCH 031/130] Added github-actions-pod yml file with dind and local beam-ga image. --- .../Kubernetes/github-actions-pod.yml | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml new file mode 100644 index 000000000000..50bc3072aab8 --- /dev/null +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: Pod +metadata: + name: github-actions-pod + labels: + role: github-actions-role +spec: + containers: + - name: github-actions-runner + image: beam-ga:latest + imagePullPolicy: Never #Remove once the image is in a public registry. + envFrom: + - secretRef: + name: github-secrets # To handle the GITHUB env variables + env: + - name: DOCKER_HOST + value: tcp://localhost:2375 + - name: dind + image: docker:20.10-dind + securityContext: + privileged: true + volumeMounts: + - name: dind-storage + mountPath: /var/lib/docker + volumes: + - name: dind-storage + emptyDir: {} + From e2c0d6e66d34ab2e606dca961001118f990dbbef Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 13 Dec 2021 13:26:03 -0600 Subject: [PATCH 032/130] Added command to install brew on MacOS --- .github/workflows/build_wheels.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 1c3e02bd8677..5423c0a0b905 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -243,7 +243,9 @@ jobs: CIBW_BEFORE_BUILD: pip install cython run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - - name: install sha512sum on MacOS + - name: Install brew on MacOS + run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + - name: Install sha512sum on MacOS if: startsWith(matrix.os_python.os, 'macos') run: brew install coreutils - name: Add checksums From 40773f40c8bd79ec933838e9020f3cd92da4feec Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 13 Dec 2021 13:59:37 -0600 Subject: [PATCH 033/130] Set brew command to PATH in MacOS. --- .github/workflows/build_wheels.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 5423c0a0b905..90d7f9112e9a 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -244,7 +244,10 @@ jobs: run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - name: Install brew on MacOS - run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + run: | + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /home/actions/.profile + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" - name: Install sha512sum on MacOS if: startsWith(matrix.os_python.os, 'macos') run: brew install coreutils From 8e578ce41a486f1287feb4a08f79b0e19a7d3683 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 15 Dec 2021 09:22:06 -0600 Subject: [PATCH 034/130] Updated Dockerfile for having the docker.sock in the volume. Added github-actions pod and secrets in k8s. --- .../dockerized-gh_actions_runners/Dockerfile | 2 +- .../Kubernetes/github-actions-pod.yml | 26 ++++++++----------- .../Kubernetes/github-actions-secrets.yml | 9 +++++++ 3 files changed, 21 insertions(+), 16 deletions(-) create mode 100644 .github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml diff --git a/.github/dockerized-gh_actions_runners/Dockerfile b/.github/dockerized-gh_actions_runners/Dockerfile index 8072d038714c..95fef3a5b2b4 100644 --- a/.github/dockerized-gh_actions_runners/Dockerfile +++ b/.github/dockerized-gh_actions_runners/Dockerfile @@ -38,5 +38,5 @@ RUN sudo chmod u+x ./entrypoint.sh RUN curl -fsSL https://get.docker.com -o get-docker.sh RUN sudo sh get-docker.sh -VOLUME [ "/var/run/docker.sock:/var/run/docker.sock"] +# VOLUME [ "/var/run/docker.sock:/var/run/docker.sock"] ENTRYPOINT ["/home/actions/entrypoint.sh"] diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml index 50bc3072aab8..444e640c6f87 100644 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml @@ -1,28 +1,24 @@ apiVersion: v1 kind: Pod metadata: - name: github-actions-pod + name: pod-github-actions labels: role: github-actions-role + name: github-actions spec: containers: - name: github-actions-runner - image: beam-ga:latest + image: ${IMAGE_URL}:latest imagePullPolicy: Never #Remove once the image is in a public registry. - envFrom: - - secretRef: - name: github-secrets # To handle the GITHUB env variables - env: - - name: DOCKER_HOST - value: tcp://localhost:2375 - - name: dind - image: docker:20.10-dind securityContext: privileged: true + envFrom: + - secretRef: + name: github-actions-secrets volumeMounts: - - name: dind-storage - mountPath: /var/lib/docker + - name: docker-sock + mountPath: /var/run/docker.sock volumes: - - name: dind-storage - emptyDir: {} - + - name: docker-sock + hostPath: + path: /var/run/docker.sock diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml new file mode 100644 index 000000000000..41d15067921f --- /dev/null +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: github-actions-secrets +type: Opaque +data: + GITHUB_TOKEN: + GITHUB_REPO: + IMAGE_URL: \ No newline at end of file From d2194326dcaebe7e6106961299b77be941b1e8d3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 16 Dec 2021 16:38:14 -0600 Subject: [PATCH 035/130] Added k8s github-actions-deployment yml file and Licensed message to the files. --- .../Kubernetes/github-actions-deployment.yml | 50 +++++++++++++++++++ .../Kubernetes/github-actions-pod.yml | 24 --------- .../Kubernetes/github-actions-secrets.yml | 18 +++++++ .../docker-compose.yml | 18 +++++++ 4 files changed, 86 insertions(+), 24 deletions(-) create mode 100644 .github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml delete mode 100644 .github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml new file mode 100644 index 000000000000..c6b08c379832 --- /dev/null +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml @@ -0,0 +1,50 @@ +################################################################################ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: github-actions-runners-deployment + labels: + name: github-actions +spec: + selector: + matchLabels: + name: github-actions + replicas: 2 + template: + metadata: + labels: + name: github-actions + spec: + containers: + - name: github-actions-runner + image: $IMAGE_URL:dev #Replace IMAGE_URL for the corresponding image url + securityContext: + privileged: true + envFrom: + - secretRef: + name: github-actions-secrets + volumeMounts: + - name: docker-sock + mountPath: /var/run/docker.sock + ports: + - containerPort: 80 + volumes: + - name: docker-sock + hostPath: + path: /var/run/docker.sock diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml deleted file mode 100644 index 444e640c6f87..000000000000 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod.yml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: pod-github-actions - labels: - role: github-actions-role - name: github-actions -spec: - containers: - - name: github-actions-runner - image: ${IMAGE_URL}:latest - imagePullPolicy: Never #Remove once the image is in a public registry. - securityContext: - privileged: true - envFrom: - - secretRef: - name: github-actions-secrets - volumeMounts: - - name: docker-sock - mountPath: /var/run/docker.sock - volumes: - - name: docker-sock - hostPath: - path: /var/run/docker.sock diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml index 41d15067921f..b1592e7a4b5c 100644 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml @@ -1,3 +1,21 @@ +################################################################################ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ + apiVersion: v1 kind: Secret metadata: diff --git a/.github/dockerized-gh_actions_runners/docker-compose.yml b/.github/dockerized-gh_actions_runners/docker-compose.yml index db9768a4fd59..e7032f46fa36 100644 --- a/.github/dockerized-gh_actions_runners/docker-compose.yml +++ b/.github/dockerized-gh_actions_runners/docker-compose.yml @@ -1,3 +1,21 @@ +################################################################################ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ + version: "3.0" services: runner: From 76034b1223ffc25fb62eab912c5f547b7f9a0fec Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 16 Dec 2021 16:48:25 -0600 Subject: [PATCH 036/130] Added k8s dind pod attempt. --- .../Kubernetes/github-actions-pod-dind.yml | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod-dind.yml diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod-dind.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod-dind.yml new file mode 100644 index 000000000000..28d5c74532d5 --- /dev/null +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod-dind.yml @@ -0,0 +1,46 @@ +################################################################################ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ + +apiVersion: v1 +kind: Pod +metadata: + name: pod-github-actions-dind + labels: + role: github-actions-role + name: github-actions +spec: + containers: + - name: github-actions-runner + image: $IMAGE_URL:dev #Replace $IMAGE_URL for the corresponding image url + envFrom: + - secretRef: + name: github-actions-secrets + env: + - name: DOCKER_HOST + value: tcp://localhost:2375 + - name: dind + image: docker:20.10-dind + securityContext: + privileged: true + volumeMounts: + - name: dind-storage + mountPath: /var/lib/docker + volumes: + - name: dind-storage + emptyDir: {} + From 077472fd9fce005d1bc23213ae24fd96f80c1f21 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Fri, 17 Dec 2021 09:50:00 -0600 Subject: [PATCH 037/130] Included Fer's java_tests changes. --- .github/workflows/build_wheels.yml | 1 + .github/workflows/java_tests.yml | 41 ++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 90d7f9112e9a..42c80efa1334 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -244,6 +244,7 @@ jobs: run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - name: Install brew on MacOS + if: startsWith(matrix.os_python.os, 'macos') run: | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /home/actions/.profile diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 9c4955d39766..e654e0d4a316 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -42,7 +42,7 @@ jobs: check_gcp_variables: timeout-minutes: 5 name: "Check GCP variables set" - runs-on: ubuntu-latest + runs-on: self-hosted outputs: gcp-variables-set: ${{ steps.check_gcp_variables.outputs.gcp-variables-set }} steps: @@ -60,7 +60,7 @@ jobs: java_unit_tests: name: 'Java Unit Tests' - runs-on: ${{ matrix.os }} + runs-on: self-hosted strategy: fail-fast: false matrix: @@ -71,7 +71,17 @@ jobs: with: persist-credentials: false submodules: recursive - # :sdks:java:core:test + - name: Install Java + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: '8' + - name: Remove default github maven configuration + # This step is a workaround to avoid a decryption issue of Beam's + # net.linguica.gradle.maven.settings plugin and github's provided maven + # settings.xml file + run: rm ~/.m2/settings.xml + # :sdks:java:core:test - name: Run :sdks:java:core:test uses: ./.github/actions/gradle-command-action with: @@ -109,7 +119,7 @@ jobs: java_wordcount_direct_runner: name: 'Java Wordcount Direct Runner' - runs-on: ${{ matrix.os }} + runs-on: self-hosted strategy: fail-fast: false matrix: @@ -120,6 +130,16 @@ jobs: with: persist-credentials: false submodules: recursive + - name: Install Java + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: '8' + - name: Remove default github maven configuration + # This step is a workaround to avoid a decryption issue of Beam's + # net.linguica.gradle.maven.settings plugin and github's provided maven + # settings.xml file + run: rm ~/.m2/settings.xml - name: Run WordCount Unix uses: ./.github/actions/gradle-command-action with: @@ -137,7 +157,7 @@ jobs: name: 'Java Wordcount Dataflow' needs: - check_gcp_variables - runs-on: ${{ matrix.os }} + runs-on: self-hosted if: | needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && ( (github.event_name == 'push' || github.event_name == 'schedule') || @@ -160,13 +180,14 @@ jobs: service_account_key: ${{ secrets.GCP_SA_KEY }} project_id: ${{ secrets.GCP_PROJECT_ID }} export_default_credentials: true - - name: Set Java Version - uses: actions/setup-java@v1 + - name: Install Java + uses: actions/setup-java@v2 with: - java-version: 8 + distribution: 'temurin' + java-version: '8' - name: Remove default github maven configuration # This step is a workaround to avoid a decryption issue of Beam's - # gradle-command-action plugin and github's provided maven + # net.linguica.gradle.maven.settings plugin and github's provided maven # settings.xml file run: rm ~/.m2/settings.xml - name: Run WordCount @@ -180,4 +201,4 @@ jobs: if: always() with: name: java_wordcount_dataflow-${{matrix.os}} - path: examples/java/build/reports/tests/integrationTest + path: examples/java/build/reports/tests/integrationTest \ No newline at end of file From ac692fec9e9327b072942ef8ef08849abe32f14a Mon Sep 17 00:00:00 2001 From: Giomar Osorio <95301399+GiomarWize@users.noreply.github.com> Date: Fri, 17 Dec 2021 14:00:55 -0500 Subject: [PATCH 038/130] Beam 12812 githubactions (#4) * fix brew and coreutils install * test only macOS in matrix strategy * remove extra settings * fix brew install command * added conditional in brew installation --- .github/workflows/build_wheels.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 42c80efa1334..46ec4dc1946a 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -243,15 +243,12 @@ jobs: CIBW_BEFORE_BUILD: pip install cython run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - - name: Install brew on MacOS + - name: Install sha512sum on MacOS if: startsWith(matrix.os_python.os, 'macos') - run: | + run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /home/actions/.profile eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" - - name: Install sha512sum on MacOS - if: startsWith(matrix.os_python.os, 'macos') - run: brew install coreutils + brew install coreutils - name: Add checksums working-directory: apache-beam-source/wheelhouse/ run: | From 645249fbb284a68110b258234dbb31c7392ab9d1 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Fri, 17 Dec 2021 13:30:21 -0600 Subject: [PATCH 039/130] Added branch beam-12812-githubactions to push and pull events. --- .github/workflows/java_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index e654e0d4a316..a213a1c875d0 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -28,10 +28,10 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*'] + branches: ['master', 'release-*', 'beam-12812-githubactions'] tags: 'v*' pull_request: - branches: ['master', 'release-*'] + branches: ['master', 'release-*', 'beam-12812-githubactions'] tags: 'v*' paths: ['sdks/java/**', 'model/**', 'runners/**', 'examples/java/**', 'examples/kotlin/**', 'release/**', 'buildSrc/**'] From b7254310c670910dc49c1cf370d353f8f52b6ac6 Mon Sep 17 00:00:00 2001 From: Elias Segundo Antonio Date: Mon, 20 Dec 2021 09:35:26 -0600 Subject: [PATCH 040/130] GCC dependency error fixed (#5) * Fix: GCC dependency installed * Fix: runner switched to self hosted Co-authored-by: Elias Segundo --- .github/workflows/go_tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index 7964636b9d76..7f26633fba85 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -29,10 +29,11 @@ on: branches: ['master', 'release-*'] tags: 'v*' paths: ['sdks/go/pkg/**'] + workflow_dispatch: jobs: build: - runs-on: ubuntu-latest + runs-on: self-hosted steps: - uses: actions/checkout@v2 with: @@ -40,6 +41,8 @@ jobs: - uses: actions/setup-go@v2 with: go-version: '1.16' + - name: Installing GCC + run: "sudo apt-get install build-essential -y" - name: Delete old coverage run: "cd sdks/go/pkg && rm -rf .coverage || :" - name: Run coverage From 87813b01685248df6274b31b92a9ed02e59d080b Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 20 Dec 2021 09:52:34 -0600 Subject: [PATCH 041/130] Added branch beam-12812-githubactions to push and pull events in go_tetst.yml --- .github/workflows/go_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index 7f26633fba85..442273ff242e 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -23,10 +23,10 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*'] + branches: ['master', 'release-*', 'beam-12812-githubactions'] tags: 'v*' pull_request: - branches: ['master', 'release-*'] + branches: ['master', 'release-*', 'beam-12812-githubactions'] tags: 'v*' paths: ['sdks/go/pkg/**'] workflow_dispatch: From def5d8c779b93c01b1c134ecb5f6b59cab874d66 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 20 Dec 2021 15:02:52 -0600 Subject: [PATCH 042/130] Added branch beam-12812-githubactions name into the checkout ref. --- .github/workflows/java_tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index a213a1c875d0..2ecb613ba467 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -130,6 +130,7 @@ jobs: with: persist-credentials: false submodules: recursive + ref: 'beam-12812-githubactions' - name: Install Java uses: actions/setup-java@v2 with: @@ -173,6 +174,7 @@ jobs: with: persist-credentials: false submodules: recursive + ref: 'beam-12812-githubactions' - name: Authenticate on GCP uses: google-github-actions/setup-gcloud@master with: From 00389b68a136f8949711930a380f7631ad74951b Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 20 Dec 2021 15:05:06 -0600 Subject: [PATCH 043/130] Removed branch beam-12812-githubactions name from push&pull triggers in go_tests.yml --- .github/workflows/go_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index 442273ff242e..7f26633fba85 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -23,10 +23,10 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*', 'beam-12812-githubactions'] + branches: ['master', 'release-*'] tags: 'v*' pull_request: - branches: ['master', 'release-*', 'beam-12812-githubactions'] + branches: ['master', 'release-*'] tags: 'v*' paths: ['sdks/go/pkg/**'] workflow_dispatch: From b64ab223266edb6664732dd55772ddc9669eb09b Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 22 Dec 2021 18:19:23 -0600 Subject: [PATCH 044/130] Added macos and windows latest to run py38 tests. --- .github/workflows/python_tests.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 1b2ff6aeeb9a..accb79326a5a 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -95,9 +95,9 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [ubuntu-latest, macos-latest, windows-latest] params: [ - {"py_ver": "3.6", "tox_env": "py36"} + {"py_ver": "3.8", "tox_env": "py38"} ] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -137,8 +137,8 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] - python: [3.6] + os: [ubuntu-latest, macos-latest, windows-latest] + python: [3.8] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 @@ -170,8 +170,8 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] - python: [3.6] + os: [ubuntu-latest, macos-latest, windows-latest] + python: [3.8] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 From c78fb4e8acee19aca1f5aec8dca11d35a3bb0b00 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 22 Dec 2021 20:38:10 -0600 Subject: [PATCH 045/130] Added py37 tests. --- .github/workflows/python_tests.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index accb79326a5a..06647dce860c 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -97,6 +97,7 @@ jobs: matrix: os: [ubuntu-latest, macos-latest, windows-latest] params: [ + {"py_ver": "3.7", "tox_env": "py37"}, {"py_ver": "3.8", "tox_env": "py38"} ] exclude: @@ -138,7 +139,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python: [3.8] + python: [3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 @@ -171,7 +172,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python: [3.8] + python: [3.7,3.8] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 From c5124b685201db90f82249d7cb05203b809a3018 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 22 Dec 2021 22:36:24 -0600 Subject: [PATCH 046/130] tox workers set to 6 --- sdks/python/scripts/run_pytest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/python/scripts/run_pytest.sh b/sdks/python/scripts/run_pytest.sh index fff73eab4f86..cd8b8b74c5dc 100755 --- a/sdks/python/scripts/run_pytest.sh +++ b/sdks/python/scripts/run_pytest.sh @@ -37,7 +37,7 @@ fi # Run with pytest-xdist and without. pytest -o junit_suite_name=${envname} \ - --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 4 ${pytest_args} --pyargs ${posargs} + --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 6 ${pytest_args} --pyargs ${posargs} status1=$? pytest -o junit_suite_name=${envname}_no_xdist \ --junitxml=pytest_${envname}_no_xdist.xml -m 'no_xdist' ${pytest_args} --pyargs ${posargs} From 6b18cd13c6f0c44316d2e23369ff731bc7db30b9 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 23 Dec 2021 06:51:20 -0600 Subject: [PATCH 047/130] Testing py37 only in ubuntu,macos and windows. --- .github/workflows/java_tests.yml | 4 ++-- .github/workflows/python_tests.yml | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 2ecb613ba467..bba2d1013615 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -28,10 +28,10 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*', 'beam-12812-githubactions'] + branches: ['master', 'release-*'] tags: 'v*' pull_request: - branches: ['master', 'release-*', 'beam-12812-githubactions'] + branches: ['master', 'release-*'] tags: 'v*' paths: ['sdks/java/**', 'model/**', 'runners/**', 'examples/java/**', 'examples/kotlin/**', 'release/**', 'buildSrc/**'] diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 06647dce860c..d7386ac9ff81 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -97,8 +97,9 @@ jobs: matrix: os: [ubuntu-latest, macos-latest, windows-latest] params: [ - {"py_ver": "3.7", "tox_env": "py37"}, - {"py_ver": "3.8", "tox_env": "py38"} + # {"py_ver": "3.6", "tox_env": "py36"}, + {"py_ver": "3.7", "tox_env": "py37"} + # {"py_ver": "3.8", "tox_env": "py38"} ] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -139,7 +140,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python: [3.7, 3.8] + python: [3.7] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 @@ -172,7 +173,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python: [3.7,3.8] + python: [3.7] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 From 0943c70e128c766dc15f20a359540654474059f5 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 23 Dec 2021 07:49:45 -0600 Subject: [PATCH 048/130] Added pip upgrade tox. Testing py37 only in windows. --- .github/workflows/python_tests.yml | 8 ++++---- sdks/python/tox.ini | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index d7386ac9ff81..775716776201 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -95,7 +95,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [windows-latest] params: [ # {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"} @@ -117,7 +117,7 @@ jobs: working-directory: ./sdks/python run: pip install -r build-requirements.txt - name: Install tox - run: pip install tox + run: pip install --upgrade pip tox - name: Run tests basic unix if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'self') working-directory: ./sdks/python @@ -139,7 +139,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [windows-latest] python: [3.7] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -172,7 +172,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [windows-latest] python: [3.7] exclude: # TODO remove exclusion after issue with protobuf is solved diff --git a/sdks/python/tox.ini b/sdks/python/tox.ini index 54f079d89950..7a4b69850d41 100644 --- a/sdks/python/tox.ini +++ b/sdks/python/tox.ini @@ -251,7 +251,7 @@ commands = /bin/sh -c "pip freeze | grep -E '(pyarrow|numpy)'" # Run pytest directly rather using run_pytest.sh. It doesn't handle # selecting tests with -m (BEAM-12985) - pytest -o junit_suite_name={envname} --junitxml=pytest_{envname}.xml -n 6 -m uses_pyarrow {posargs} + pytest -o junit_suite_name={envname} --junitxml=pytest_{envname}.xml -n 3 -m uses_pyarrow {posargs} [testenv:py{36,37,38}-pandas-{11,12,13}] deps = From 8eafcec51159597df49fa75199eecbd71cff5715 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 23 Dec 2021 08:00:31 -0600 Subject: [PATCH 049/130] Added pip upgrade only for windows os --- .github/workflows/python_tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 775716776201..e82fdb5b52ca 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -116,10 +116,14 @@ jobs: - name: Get build dependencies working-directory: ./sdks/python run: pip install -r build-requirements.txt + - name: Install tox (Windows) + if: startsWith(matrix.os, 'windows') + run: sudo -H pip install --upgrade pip tox virtualenv - name: Install tox run: pip install --upgrade pip tox + if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') - name: Run tests basic unix - if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'self') + if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') working-directory: ./sdks/python run: tox -c tox.ini -e ${{ matrix.params.tox_env }} - name: Run tests basic windows From 62a9457a716e8f721af1d604322c9484ae431989 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 23 Dec 2021 08:02:09 -0600 Subject: [PATCH 050/130] Remove sudo from pip upgrade wOS --- .github/workflows/python_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index e82fdb5b52ca..4949d70274a4 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -118,7 +118,7 @@ jobs: run: pip install -r build-requirements.txt - name: Install tox (Windows) if: startsWith(matrix.os, 'windows') - run: sudo -H pip install --upgrade pip tox virtualenv + run: pip install --upgrade pip tox virtualenv - name: Install tox run: pip install --upgrade pip tox if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') From 759f8566b8cfd1023db27ae9bbe5fc06ae6109a6 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 23 Dec 2021 08:12:36 -0600 Subject: [PATCH 051/130] Single pip install if not wOS --- .github/workflows/python_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 4949d70274a4..b8ea2b7e0080 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -120,7 +120,7 @@ jobs: if: startsWith(matrix.os, 'windows') run: pip install --upgrade pip tox virtualenv - name: Install tox - run: pip install --upgrade pip tox + run: pip install tox if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') - name: Run tests basic unix if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') From e363dcc9770a03aa664cea3a9e5abb197d1d7762 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 23 Dec 2021 08:19:39 -0600 Subject: [PATCH 052/130] Added py versions for testing in all the versions. Commented windows tox for the moment for testing resources. --- .github/workflows/python_tests.yml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index b8ea2b7e0080..3cfad28f29d0 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -95,11 +95,11 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-latest] + os: [ubuntu-latest, macos-latest, windows-latest] params: [ - # {"py_ver": "3.6", "tox_env": "py36"}, - {"py_ver": "3.7", "tox_env": "py37"} - # {"py_ver": "3.8", "tox_env": "py38"} + {"py_ver": "3.6", "tox_env": "py36"}, + {"py_ver": "3.7", "tox_env": "py37"}, + {"py_ver": "3.8", "tox_env": "py38"} ] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -116,9 +116,10 @@ jobs: - name: Get build dependencies working-directory: ./sdks/python run: pip install -r build-requirements.txt - - name: Install tox (Windows) - if: startsWith(matrix.os, 'windows') - run: pip install --upgrade pip tox virtualenv + # Commented by the moment to run memory&cpu resources. +# - name: Install tox (Windows) +# if: startsWith(matrix.os, 'windows') +# run: pip install --upgrade pip tox virtualenv - name: Install tox run: pip install tox if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') @@ -143,8 +144,8 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-latest] - python: [3.7] + os: [ubuntu-latest, macos-latest, windows-latest] + python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 @@ -176,8 +177,8 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-latest] - python: [3.7] + os: [ubuntu-latest, macos-latest, windows-latest] + python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved # https://github.com/protocolbuffers/protobuf/issues/7765 From 54c16ba5ec0710a99fd5efe33a413acf883ebc91 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 23 Dec 2021 10:28:24 -0600 Subject: [PATCH 053/130] Kubernetes vertical and horizontal pod autoscaling files added. Included preStop container lifecycle instruction in order to delete the terminated containers from the GitHub Actions Account. --- .../Kubernetes/github-actions-deployment.yml | 12 ++++++-- .../Kubernetes/github-actions-hpa.yml | 29 +++++++++++++++++++ .../Kubernetes/github-actions-vpa.yml | 28 ++++++++++++++++++ .github/workflows/java_tests.yml | 2 -- 4 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 .github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml create mode 100644 .github/dockerized-gh_actions_runners/Kubernetes/github-actions-vpa.yml diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml index c6b08c379832..3b64a40ad423 100644 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml @@ -33,7 +33,7 @@ spec: spec: containers: - name: github-actions-runner - image: $IMAGE_URL:dev #Replace IMAGE_URL for the corresponding image url + image: $IMAGE_URL:dev # replace variable manually securityContext: privileged: true envFrom: @@ -42,8 +42,14 @@ spec: volumeMounts: - name: docker-sock mountPath: /var/run/docker.sock - ports: - - containerPort: 80 + resources: + requests: + memory: "1024Mi" + cpu: "2" + lifecycle: + preStop: + exec: + command: [./config.sh remove --token $GITHUB_TOKEN] # replace variable manually volumes: - name: docker-sock hostPath: diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml new file mode 100644 index 000000000000..b55cb09600a4 --- /dev/null +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml @@ -0,0 +1,29 @@ +################################################################################ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: hpa-github-actions +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: github-actions-runners-deployment + minReplicas: 1 + maxReplicas: 10 + targetCPUUtilizationPercentage: 50 diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-vpa.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-vpa.yml new file mode 100644 index 000000000000..c4a4add74571 --- /dev/null +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-vpa.yml @@ -0,0 +1,28 @@ +################################################################################ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: vpa-github-actions +spec: + targetRef: + apiVersion: "apps/v1" + kind: Deployment + name: github-actions-runners-deployment + updatePolicy: + updateMode: "Auto" diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index bba2d1013615..e654e0d4a316 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -130,7 +130,6 @@ jobs: with: persist-credentials: false submodules: recursive - ref: 'beam-12812-githubactions' - name: Install Java uses: actions/setup-java@v2 with: @@ -174,7 +173,6 @@ jobs: with: persist-credentials: false submodules: recursive - ref: 'beam-12812-githubactions' - name: Authenticate on GCP uses: google-github-actions/setup-gcloud@master with: From 6ab41e5c066eb7fb475125dd9b52b3d083aca693 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 10:29:53 -0600 Subject: [PATCH 054/130] Commented Run test basic windows step to run the rest of the steps. --- .github/workflows/python_tests.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 3cfad28f29d0..91144ec5c946 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -116,10 +116,9 @@ jobs: - name: Get build dependencies working-directory: ./sdks/python run: pip install -r build-requirements.txt - # Commented by the moment to run memory&cpu resources. -# - name: Install tox (Windows) -# if: startsWith(matrix.os, 'windows') -# run: pip install --upgrade pip tox virtualenv + - name: Install tox (Windows) + if: startsWith(matrix.os, 'windows') + run: pip install --upgrade pip tox virtualenv - name: Install tox run: pip install tox if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') @@ -127,10 +126,11 @@ jobs: if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') working-directory: ./sdks/python run: tox -c tox.ini -e ${{ matrix.params.tox_env }} - - name: Run tests basic windows - if: startsWith(matrix.os, 'windows') - working-directory: ./sdks/python - run: tox -c tox.ini -e ${{ matrix.params.tox_env }}-win + # Commented by the moment to run memory&cpu resources. +# - name: Run tests basic windows +# if: startsWith(matrix.os, 'windows') +# working-directory: ./sdks/python +# run: tox -c tox.ini -e ${{ matrix.params.tox_env }}-win - name: Upload test logs uses: actions/upload-artifact@v2 if: always() From 28359759f2f7fd0352a6799d62e7b8a0db5e9379 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 12:52:28 -0600 Subject: [PATCH 055/130] Running on windowsOS only and reduced pytest nodes to 2. --- .github/workflows/python_tests.yml | 14 +++++++------- sdks/python/scripts/run_pytest.sh | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 91144ec5c946..68e57f3b941e 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -95,7 +95,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [windows-latest] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, @@ -127,10 +127,10 @@ jobs: working-directory: ./sdks/python run: tox -c tox.ini -e ${{ matrix.params.tox_env }} # Commented by the moment to run memory&cpu resources. -# - name: Run tests basic windows -# if: startsWith(matrix.os, 'windows') -# working-directory: ./sdks/python -# run: tox -c tox.ini -e ${{ matrix.params.tox_env }}-win + - name: Run tests basic windows + if: startsWith(matrix.os, 'windows') + working-directory: ./sdks/python + run: tox -c tox.ini -e ${{ matrix.params.tox_env }}-win - name: Upload test logs uses: actions/upload-artifact@v2 if: always() @@ -144,7 +144,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [windows-latest] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -177,7 +177,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [windows-latest] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved diff --git a/sdks/python/scripts/run_pytest.sh b/sdks/python/scripts/run_pytest.sh index cd8b8b74c5dc..dd12b2e92e4f 100755 --- a/sdks/python/scripts/run_pytest.sh +++ b/sdks/python/scripts/run_pytest.sh @@ -37,7 +37,7 @@ fi # Run with pytest-xdist and without. pytest -o junit_suite_name=${envname} \ - --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 6 ${pytest_args} --pyargs ${posargs} + --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 2 ${pytest_args} --pyargs ${posargs} status1=$? pytest -o junit_suite_name=${envname}_no_xdist \ --junitxml=pytest_${envname}_no_xdist.xml -m 'no_xdist' ${pytest_args} --pyargs ${posargs} From 2b78c0165f7fc8add9b5d76f8ffb19020f2a4f20 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 14:01:33 -0600 Subject: [PATCH 056/130] Using ubuntu-latest for testing winOS --- .github/workflows/python_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 68e57f3b941e..70269d3322cc 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,7 +91,7 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: self-hosted + runs-on: ubuntu-latest strategy: fail-fast: false matrix: From 8bde9783e821d4fa5feb764fdcceaa38843290c3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 14:06:23 -0600 Subject: [PATCH 057/130] Using ubuntu-latest for testing winOS --- .github/workflows/python_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 70269d3322cc..83da403e8dbb 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,7 +91,7 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: @@ -99,7 +99,7 @@ jobs: params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, - {"py_ver": "3.8", "tox_env": "py38"} + {"py_ver": "3.8", "tox_env": "py38"}, ] exclude: # TODO remove exclusion after issue with protobuf is solved From 4a056a550cb112ed1018604dd5c4c3989aebb287 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 14:14:14 -0600 Subject: [PATCH 058/130] Added matrix.os to run windows os --- .github/workflows/python_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 83da403e8dbb..f08fa8741a8c 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,7 +91,7 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: ${{ matrix.os }} + runs-on: [self-hosted, ${{ matrix.os }}] strategy: fail-fast: false matrix: From 529d7485fd2710bdd50b7c7be136e218dbb50944 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 14:15:51 -0600 Subject: [PATCH 059/130] Added windows-latest in runs-on --- .github/workflows/python_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index f08fa8741a8c..06f5a8478797 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,7 +91,7 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: [self-hosted, ${{ matrix.os }}] + runs-on: [self-hosted, windows-latest] strategy: fail-fast: false matrix: From fbeb7714399a1bf316abbdf9df1dd64696efc0df Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 14:22:52 -0600 Subject: [PATCH 060/130] Updated runs-on --- .github/workflows/python_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 06f5a8478797..7494987923b7 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,11 +91,11 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: [self-hosted, windows-latest] + runs-on: ${{matrix.os}} strategy: fail-fast: false matrix: - os: [windows-latest] + os: [self-hosted, windows-latest] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, From 8d0fb5040fbf5f00cf4f5766fdf11f35d7ada9d3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 14:29:14 -0600 Subject: [PATCH 061/130] Updated runs-on and matrix.os --- .github/workflows/python_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 7494987923b7..fc06ce5c9599 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,11 +91,11 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: ${{matrix.os}} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [self-hosted, windows-latest] + os: [[self-hosted, ubuntu-latest],[self-hosted, macos-latest], [self-hosted, windows-latest]] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, From b507ba05a323e3778e15f60954b17fcb9c8ab63a Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 15:04:51 -0600 Subject: [PATCH 062/130] Updated build_playground_backend.yml, build_playground_frontend.yml and cancel.yml files to runs-on self-hosted runners. --- .github/workflows/build_playground_backend.yml | 2 +- .github/workflows/build_playground_frontend.yml | 2 +- .github/workflows/cancel.yml | 2 +- .github/workflows/python_tests.yml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_playground_backend.yml b/.github/workflows/build_playground_backend.yml index 48eab26b2a9e..f1e8308d2fa9 100644 --- a/.github/workflows/build_playground_backend.yml +++ b/.github/workflows/build_playground_backend.yml @@ -25,7 +25,7 @@ on: jobs: build_playground_backend_docker_image: name: Build Playground Backend App - runs-on: ubuntu-latest + runs-on: self-hosted env: GO_VERSION: 1.17.0 BEAM_VERSION: 2.33.0 diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index ee1bed8f2b5a..f23440381354 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -25,7 +25,7 @@ on: jobs: build_playground_frontend_docker_image: name: Build Playground Frontend App - runs-on: ubuntu-latest + runs-on: self-hosted env: GO_VERSION: 1.17.0 BEAM_VERSION: 2.33.0 diff --git a/.github/workflows/cancel.yml b/.github/workflows/cancel.yml index ea46ebf89d36..c8b1ff895081 100644 --- a/.github/workflows/cancel.yml +++ b/.github/workflows/cancel.yml @@ -28,7 +28,7 @@ on: jobs: cancel-duplicate-workflow-runs: name: "Cancel duplicate workflow runs" - runs-on: ubuntu-latest + runs-on: self-hosted steps: - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" uses: actions/checkout@v2 diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index fc06ce5c9599..27e69e6827aa 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,11 +91,11 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: ${{ matrix.os }} + runs-on: self-hosted strategy: fail-fast: false matrix: - os: [[self-hosted, ubuntu-latest],[self-hosted, macos-latest], [self-hosted, windows-latest]] + os: [ubuntu, macos, windows] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, From 73ed95c8b3101b856be4887194f952985e84d178 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 17:11:18 -0600 Subject: [PATCH 063/130] Self hosted winwos --- .github/workflows/python_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 27e69e6827aa..4f0c86f6cb78 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,11 +91,11 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: self-hosted + runs-on: [self-hosted, windows] strategy: fail-fast: false matrix: - os: [ubuntu, macos, windows] + os: [windows] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, From 388c76acb6ca1707ebff4c5b204505012ec9fc7b Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 19:22:53 -0600 Subject: [PATCH 064/130] Updated build_wheels.yml runs-on step --- .github/workflows/build_wheels.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 46ec4dc1946a..531c4c2a9234 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,11 +203,11 @@ jobs: needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} - runs-on: [self-hosted] + runs-on: ${{ matrix.os_python.os }} strategy: matrix: os_python: [ - {"os": "ubuntu-latest", "python": "cp36-* cp37-* cp38-*"}, + {"os": "self-hosted", "python": "cp36-* cp37-* cp38-*"}, {"os": "macos-latest", "python": "cp36-* cp37-* cp38-*"}, {"os": "windows-latest", "python": "cp36-* cp37-* cp38-*"}, ] @@ -293,7 +293,7 @@ jobs: if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: - os : [self-hosted, ubuntu-latest, macos-latest, windows-latest] + os : [self-hosted, macos-latest, windows-latest] steps: - name: Download wheels from artifacts uses: actions/download-artifact@v2 From cad12dd09fb9ad47bd2ca14dbe0c37ffdb27218f Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 19:42:14 -0600 Subject: [PATCH 065/130] Install dependencies step added in build_playground_backend.yml --- .github/workflows/build_playground_backend.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build_playground_backend.yml b/.github/workflows/build_playground_backend.yml index f1e8308d2fa9..5ff77c1a25ec 100644 --- a/.github/workflows/build_playground_backend.yml +++ b/.github/workflows/build_playground_backend.yml @@ -40,6 +40,8 @@ jobs: - uses: actions/setup-go@v2 with: go-version: '${{ env.GO_VERSION }}' + - name: Install dependencies + run: sudo apt update && sudo apt install libsnmp-dev -y - name: Remove default github maven configuration # This step is a workaround to avoid a decryption issue run: rm ~/.m2/settings.xml From ceb91dfbde64b8e040398906703c345d5993532e Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 20:37:05 -0600 Subject: [PATCH 066/130] Updated runs-on to run over the matrix.os array including self-hosted (ubuntu) os. --- .github/workflows/java_tests.yml | 12 ++++++------ .github/workflows/local_env_tests.yml | 2 +- .github/workflows/python_tests.yml | 16 ++++++++-------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index e654e0d4a316..e46385b9ed8f 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -60,11 +60,11 @@ jobs: java_unit_tests: name: 'Java Unit Tests' - runs-on: self-hosted + runs-on: ${{ matrix.ox }} strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [self-hosted, macos-latest, windows-latest] steps: - name: Checkout code uses: actions/checkout@v2 @@ -119,11 +119,11 @@ jobs: java_wordcount_direct_runner: name: 'Java Wordcount Direct Runner' - runs-on: self-hosted + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [self-hosted, macos-latest, windows-latest] steps: - name: Checkout code uses: actions/checkout@v2 @@ -157,7 +157,7 @@ jobs: name: 'Java Wordcount Dataflow' needs: - check_gcp_variables - runs-on: self-hosted + runs-on: ${{ matrix.os }} if: | needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && ( (github.event_name == 'push' || github.event_name == 'schedule') || @@ -166,7 +166,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [self-hosted, macos-latest, windows-latest] steps: - name: Checkout code uses: actions/checkout@v2 diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index 2bf6af1c6a88..dd28bdb7a902 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -32,7 +32,7 @@ jobs: run_local_env_install_ubuntu: timeout-minutes: 25 name: "Ubuntu run local environment shell script" - runs-on: ubuntu-latest + runs-on: self-hosted steps: - uses: actions/checkout@v2 - name: "Installing local env dependencies" diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 4f0c86f6cb78..ecc7a00e27ae 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -91,11 +91,11 @@ jobs: python_unit_tests: name: 'Python Unit Tests' - runs-on: [self-hosted, windows] + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [windows] + os: [self-hosted, macos-latest, windows-latest] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, @@ -121,9 +121,9 @@ jobs: run: pip install --upgrade pip tox virtualenv - name: Install tox run: pip install tox - if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') + if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - name: Run tests basic unix - if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') + if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') working-directory: ./sdks/python run: tox -c tox.ini -e ${{ matrix.params.tox_env }} # Commented by the moment to run memory&cpu resources. @@ -140,11 +140,11 @@ jobs: python_wordcount_direct_runner: name: 'Python Wordcount Direct Runner' - runs-on: self-hosted + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [windows-latest] + os: [self-hosted, macos-latest, windows-latest] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -173,11 +173,11 @@ jobs: name: 'Python Wordcount Dataflow' needs: - build_python_sdk_source - runs-on: self-hosted + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [windows-latest] + os: [self-hosted, macos-latest, windows-latest] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved From 6659e8e715367a5e3500408561f6fcd3559abf8e Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 21:46:13 -0600 Subject: [PATCH 067/130] Added workflow run when pushing to 'beam-12812-githubactions' branch for testing purpose. --- .github/workflows/go_tests.yml | 2 +- .github/workflows/java_tests.yml | 2 +- .github/workflows/local_env_tests.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index 7f26633fba85..7ca8179578c7 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -23,7 +23,7 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*'] + branches: ['master', 'release-*', 'beam-12812-githubactions'] tags: 'v*' pull_request: branches: ['master', 'release-*'] diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index e46385b9ed8f..3cdef4f93653 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -28,7 +28,7 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*'] + branches: ['master', 'release-*', 'beam-12812-githubactions'] tags: 'v*' pull_request: branches: ['master', 'release-*'] diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index dd28bdb7a902..756410f96546 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -21,7 +21,7 @@ name: Local environment tests on: push: - branches: ['master', 'release-*'] + branches: ['master', 'release-*', 'beam-12812-githubactions'] tags: 'v*' pull_request: branches: ['master', 'release-*'] From 0efca1f39a5dc50a51e3a79fa2d01a72c1762de5 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 21:56:33 -0600 Subject: [PATCH 068/130] Fixed typo in matrix.os runs-on variable. Added Install Java step in local_env_tests.yml to fix missing JAVA_HOME variable test error. --- .github/workflows/java_tests.yml | 2 +- .github/workflows/local_env_tests.yml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 3cdef4f93653..abb828b54d9f 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -60,7 +60,7 @@ jobs: java_unit_tests: name: 'Java Unit Tests' - runs-on: ${{ matrix.ox }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index 756410f96546..1b8bec46196c 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -38,6 +38,11 @@ jobs: - name: "Installing local env dependencies" run: "sudo ./local-env-setup.sh" id: local_env_install_ubuntu + - name: Install Java + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: '8' - name: "Gradle check" run: "./gradlew checkSetup" id: local_env_install_gradle_check_ubuntu From 77f29fff44adfc334d1ea324b330c721b4442fe9 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 27 Dec 2021 22:11:30 -0600 Subject: [PATCH 069/130] Added Install py3 venv step in local_env_tests.yml --- .github/workflows/local_env_tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index 1b8bec46196c..a18c854935b9 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -43,6 +43,8 @@ jobs: with: distribution: 'temurin' java-version: '8' + - name: Install python3 venv + run: apt install python3.8-venv - name: "Gradle check" run: "./gradlew checkSetup" id: local_env_install_gradle_check_ubuntu From 8cc396a6cb342ac5e35d9ce9e48e2f4cf7ce9db1 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 28 Dec 2021 07:38:23 -0600 Subject: [PATCH 070/130] Fixed Install py3 venv command in local_env_tests --- .github/workflows/local_env_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index a18c854935b9..c523c1fd0e0e 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -44,7 +44,7 @@ jobs: distribution: 'temurin' java-version: '8' - name: Install python3 venv - run: apt install python3.8-venv + run: sudo apt install python3.8-venv -y - name: "Gradle check" run: "./gradlew checkSetup" id: local_env_install_gradle_check_ubuntu From 24671af27d3db76bf7feb6c85c765cd253cbb404 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 28 Dec 2021 10:00:09 -0600 Subject: [PATCH 071/130] Removed brew install commands in build_wheels --- .github/workflows/build_wheels.yml | 7 ++----- .github/workflows/local_env_tests.yml | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 531c4c2a9234..e7d383f00eac 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -245,10 +245,7 @@ jobs: shell: bash - name: Install sha512sum on MacOS if: startsWith(matrix.os_python.os, 'macos') - run: - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" - brew install coreutils + run: brew install coreutils - name: Add checksums working-directory: apache-beam-source/wheelhouse/ run: | @@ -289,7 +286,7 @@ jobs: needs: - build_wheels - check_gcp_variables - runs-on: [self-hosted] + runs-on: self-hosted if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index c523c1fd0e0e..d8fdef9985b1 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -31,7 +31,7 @@ on: jobs: run_local_env_install_ubuntu: timeout-minutes: 25 - name: "Ubuntu run local environment shell script" + name: "Self-hosted run local environment shell script" runs-on: self-hosted steps: - uses: actions/checkout@v2 From a8c56e6b5b42c1d69559f447a8de924f080bb854 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 28 Dec 2021 13:26:00 -0600 Subject: [PATCH 072/130] Remove Install build esentials from go_tests.yml as the current Docker image has the libraries installed. --- .github/workflows/go_tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index 7ca8179578c7..ea9eb573e953 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -41,8 +41,6 @@ jobs: - uses: actions/setup-go@v2 with: go-version: '1.16' - - name: Installing GCC - run: "sudo apt-get install build-essential -y" - name: Delete old coverage run: "cd sdks/go/pkg && rm -rf .coverage || :" - name: Run coverage From 9d4ce0eb5299edd53ee43d059e80e77a807cebf6 Mon Sep 17 00:00:00 2001 From: Giomar Osorio <95301399+GiomarWize@users.noreply.github.com> Date: Tue, 28 Dec 2021 19:43:04 -0500 Subject: [PATCH 073/130] Updated Dockerfile of the linux self-hosted runner (#6) --- .github/dockerized-gh_actions_runners/Dockerfile | 9 +++++---- .github/dockerized-gh_actions_runners/entrypoint.sh | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/dockerized-gh_actions_runners/Dockerfile b/.github/dockerized-gh_actions_runners/Dockerfile index 95fef3a5b2b4..65faea46c9ef 100644 --- a/.github/dockerized-gh_actions_runners/Dockerfile +++ b/.github/dockerized-gh_actions_runners/Dockerfile @@ -20,9 +20,9 @@ FROM ubuntu:20.04 ARG RUNNER_VERSION=2.285.1 -RUN apt-get -yqq update && apt-get install -yqq curl sudo git jq unzip tar gnupg2 apt-transport-https ca-certificates -RUN apt-get install -yqq liblttng-ust0 libkrb5-3 zlib1g libssl1.1 -RUN DEBIAN_FRONTEND=noninteractive apt-get install -yqq libicu66 +RUN apt-get -yqq update +#Install APT packages +RUN DEBIAN_FRONTEND=noninteractive apt-get install -yqq acl aria2 apt-transport-https binutils bison brotli build-essential bzip2 ca-certificates coreutils curl dbus dnsutils dpkg fakeroot file flex fonts-noto-color-emoji ftp gnupg2 haveged imagemagick iproute2 iputils-ping jq lib32z1 libc++-dev libc++abi-dev libcurl4 libgbm-dev libgconf-2-4 libgsl-dev libgtk-3-0 libicu66 libkrb5-3 liblttng-ust0 libmagic-dev libmagickcore-dev libmagickwand-dev libsecret-1-dev libssl1.1 libsqlite3-dev libxss1 locales m4 mediainfo mercurial net-tools netcat openssh-client p7zip-full p7zip-rar parallel pass patchelf pkg-config pollinate python-is-python3 rpm rsync shellcheck sqlite3 ssh sshpass subversion sudo swig telnet texinfo time tk tzdata unzip upx wget xorriso xvfb xz-utils zip zlib1g zsync RUN apt-get clean RUN rm -rf /var/lib/apt/lists/* RUN useradd -m actions && usermod -aG sudo actions && echo "%sudo ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers @@ -39,4 +39,5 @@ RUN curl -fsSL https://get.docker.com -o get-docker.sh RUN sudo sh get-docker.sh # VOLUME [ "/var/run/docker.sock:/var/run/docker.sock"] -ENTRYPOINT ["/home/actions/entrypoint.sh"] +CMD ["/home/actions/entrypoint.sh"] +ENTRYPOINT ["/bin/bash"] diff --git a/.github/dockerized-gh_actions_runners/entrypoint.sh b/.github/dockerized-gh_actions_runners/entrypoint.sh index f6830a26c96f..ae684817522b 100644 --- a/.github/dockerized-gh_actions_runners/entrypoint.sh +++ b/.github/dockerized-gh_actions_runners/entrypoint.sh @@ -30,7 +30,8 @@ export RUNNER_TOKEN --url https://github.com/$GITHUB_REPO/beam \ --work _work \ --unattended \ - --replace + --replace \ + --labels ubuntu-20.04,ubuntu-latest remove() { ./config.sh remove --unattended --token "${RUNNER_TOKEN}" From 6c1d75ca22db411e112c9c23c43dc6a307cb5a04 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 4 Jan 2022 19:46:40 -0600 Subject: [PATCH 074/130] Updated entrypoint.sh to scapping GITHUB_TOKEN variable that was causing an issue when running the cluster. Included Clean Workspace step in python_tests.yml --- .github/dockerized-gh_actions_runners/Dockerfile | 1 - .github/dockerized-gh_actions_runners/entrypoint.sh | 2 +- .github/workflows/python_tests.yml | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/dockerized-gh_actions_runners/Dockerfile b/.github/dockerized-gh_actions_runners/Dockerfile index 65faea46c9ef..f8cd8d806f52 100644 --- a/.github/dockerized-gh_actions_runners/Dockerfile +++ b/.github/dockerized-gh_actions_runners/Dockerfile @@ -38,6 +38,5 @@ RUN sudo chmod u+x ./entrypoint.sh RUN curl -fsSL https://get.docker.com -o get-docker.sh RUN sudo sh get-docker.sh -# VOLUME [ "/var/run/docker.sock:/var/run/docker.sock"] CMD ["/home/actions/entrypoint.sh"] ENTRYPOINT ["/bin/bash"] diff --git a/.github/dockerized-gh_actions_runners/entrypoint.sh b/.github/dockerized-gh_actions_runners/entrypoint.sh index ae684817522b..9f1aedcbf7f9 100644 --- a/.github/dockerized-gh_actions_runners/entrypoint.sh +++ b/.github/dockerized-gh_actions_runners/entrypoint.sh @@ -19,7 +19,7 @@ sudo chmod 666 /var/run/docker.sock registration_url="https://api.github.com/repos/$GITHUB_REPO/beam/actions/runners/registration-token" echo "Requesting registration URL at '${registration_url}'" - +GITHUB_TOKEN=$(echo $GITHUB_TOKEN) #scaping GITHUB_TOKEN variable payload=$(curl -sX POST -H "Authorization: token $GITHUB_TOKEN" ${registration_url}) RUNNER_TOKEN=$(echo $payload | jq '.token' --raw-output) export RUNNER_TOKEN diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index ecc7a00e27ae..9ccb1a634579 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -107,6 +107,8 @@ jobs: - os: windows-latest params: {"py_ver": "3.8", "tox_env": "py38"} steps: + - name: Clean GitHub Workspace + run: rm -rf $GITHUB_WORKSPACE/* - name: Checkout code uses: actions/checkout@v2 - name: Install python From 1a17a5d619dcdacc3f4c415defd5c462a1c9d67d Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 4 Jan 2022 20:05:18 -0600 Subject: [PATCH 075/130] Added Clean GitHub workspace step in python_tests.yml for every checkout use. --- .github/workflows/python_tests.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 9ccb1a634579..8b1bf93e9c07 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -107,8 +107,8 @@ jobs: - os: windows-latest params: {"py_ver": "3.8", "tox_env": "py38"} steps: - - name: Clean GitHub Workspace - run: rm -rf $GITHUB_WORKSPACE/* + - name: Clean GitHub workspace + run: rm -r $GITHUB_WORKSPACE/* - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -154,6 +154,8 @@ jobs: - os: windows-latest python: 3.8 steps: + - name: Clean GitHub workspace + run: rm -r $GITHUB_WORKSPACE/* - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -187,6 +189,8 @@ jobs: - os: windows-latest python: 3.8 steps: + - name: Clean GitHub workspace + run: rm -r $GITHUB_WORKSPACE/* - name: Checkout code uses: actions/checkout@v2 - name: Install python From d869c0f599e79559720a9d8e6a6ad809154e1c8f Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 4 Jan 2022 20:34:44 -0600 Subject: [PATCH 076/130] Added if conditions to remove only if the directory exists and os is different from windows --- .github/workflows/python_tests.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 8b1bf93e9c07..20b29b8cb4ea 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -108,7 +108,8 @@ jobs: params: {"py_ver": "3.8", "tox_env": "py38"} steps: - name: Clean GitHub workspace - run: rm -r $GITHUB_WORKSPACE/* + if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') + run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -155,6 +156,7 @@ jobs: python: 3.8 steps: - name: Clean GitHub workspace + if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') run: rm -r $GITHUB_WORKSPACE/* - name: Checkout code uses: actions/checkout@v2 @@ -190,7 +192,8 @@ jobs: python: 3.8 steps: - name: Clean GitHub workspace - run: rm -r $GITHUB_WORKSPACE/* + if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') + run: rm -rf $GITHUB_WORKSPACE/* - name: Checkout code uses: actions/checkout@v2 - name: Install python From 7e9ca7135d4dda6a0af15812685feacf9d8c7a4d Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 4 Jan 2022 20:56:48 -0600 Subject: [PATCH 077/130] Testing Clean workspace for Windows --- .github/workflows/python_tests.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 20b29b8cb4ea..20590f135f2d 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -157,7 +157,10 @@ jobs: steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - run: rm -r $GITHUB_WORKSPACE/* + run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE/* ; fi + - name: Clean GitHub workspace Windows + if: startsWith(matrix.os, 'windows') + run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -r -fo $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -193,7 +196,7 @@ jobs: steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - run: rm -rf $GITHUB_WORKSPACE/* + run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 - name: Install python From 943e7cfe5b5abd996cbc10752e5b6709382ee2be Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 5 Jan 2022 11:34:37 -0600 Subject: [PATCH 078/130] Testing Clean workspace for Windows and removing if condiiton --- .github/workflows/python_tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 20590f135f2d..5e56fa957666 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -157,10 +157,10 @@ jobs: steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE/* ; fi + run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE ; fi - name: Clean GitHub workspace Windows if: startsWith(matrix.os, 'windows') - run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -r -fo $GITHUB_WORKSPACE/* ; fi + run: rm -r -fo $GITHUB_WORKSPACE - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -196,7 +196,7 @@ jobs: steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE/* ; fi + run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE ; fi - name: Checkout code uses: actions/checkout@v2 - name: Install python From d5dd83a5b4f2642b97ba767a28cd4ff417bdaf6c Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 5 Jan 2022 11:47:02 -0600 Subject: [PATCH 079/130] Added privileges to remove GitHub Workspace command. --- .github/workflows/python_tests.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 5e56fa957666..91b78efeee77 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -109,7 +109,7 @@ jobs: steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE/* ; fi + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE ; fi - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -157,10 +157,10 @@ jobs: steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE ; fi + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE ; fi - name: Clean GitHub workspace Windows if: startsWith(matrix.os, 'windows') - run: rm -r -fo $GITHUB_WORKSPACE + run: echo TODO commands to clean workspace in self-hosted-windows - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -196,7 +196,10 @@ jobs: steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - run: if [ -d "$GITHUB_WORKSPACE" ]; then rm -rf $GITHUB_WORKSPACE ; fi + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi + - name: Clean GitHub workspace Windows + if: startsWith(matrix.os, 'windows') + run: echo TODO commands to clean workspace in self-hosted-windows - name: Checkout code uses: actions/checkout@v2 - name: Install python From df9d9808bf587e23f95657871293173dbd24f6d2 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 5 Jan 2022 15:14:19 -0600 Subject: [PATCH 080/130] Added * to remove GitHub Workspace files --- .github/workflows/python_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 91b78efeee77..a3fb59ada0e0 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -109,7 +109,7 @@ jobs: steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE ; fi + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -157,7 +157,7 @@ jobs: steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE ; fi + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Clean GitHub workspace Windows if: startsWith(matrix.os, 'windows') run: echo TODO commands to clean workspace in self-hosted-windows From 558d731bcf6a74bd2c0a153cb22e31950eb92e4b Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 5 Jan 2022 18:41:15 -0600 Subject: [PATCH 081/130] Added Clear GitHub Workspace step for Check GCP Variables job. --- .github/workflows/python_tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index a3fb59ada0e0..a647af550ffd 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -45,6 +45,8 @@ jobs: outputs: gcp-variables-set: ${{ steps.check_gcp_variables.outputs.gcp-variables-set }} steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - uses: actions/checkout@v2 - name: "Check are GCP variables set" run: "./scripts/ci/ci_check_are_gcp_variables_set.sh" From 6acaab0c57c358571a9dd56a1e121920b4d4a5b7 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 5 Jan 2022 19:02:41 -0600 Subject: [PATCH 082/130] Added Clean Workspace for Build python source distribution job. --- .github/workflows/python_tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index a647af550ffd..e87bc179b8ae 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -70,6 +70,8 @@ jobs: - check_gcp_variables runs-on: self-hosted steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 - name: Install python From 8b91eb30890c7e7d87ae0c6b0010f95c9c29852b Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 5 Jan 2022 19:56:55 -0600 Subject: [PATCH 083/130] Added Clean Workspace step in all the workflows.yml files --- .github/workflows/build_playground_backend.yml | 2 ++ .github/workflows/build_playground_frontend.yml | 2 ++ .github/workflows/build_wheels.yml | 6 ++++++ .github/workflows/cancel.yml | 2 ++ .github/workflows/go_tests.yml | 2 ++ .github/workflows/java_tests.yml | 11 +++++++++++ .github/workflows/local_env_tests.yml | 2 ++ .github/workflows/python_tests.yml | 6 +++--- 8 files changed, 30 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_playground_backend.yml b/.github/workflows/build_playground_backend.yml index 5ff77c1a25ec..9576ed928d05 100644 --- a/.github/workflows/build_playground_backend.yml +++ b/.github/workflows/build_playground_backend.yml @@ -31,6 +31,8 @@ jobs: BEAM_VERSION: 2.33.0 TERRAFORM_VERSION: 1.0.9 steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Check out the repo uses: actions/checkout@v2 - name: Set up JDK 1.8 diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index f23440381354..998c2218cbd8 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -31,6 +31,8 @@ jobs: BEAM_VERSION: 2.33.0 TERRAFORM_VERSION: 1.0.9 steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Check out the repo uses: actions/checkout@v2 - name: Set up JDK 1.8 diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index e7d383f00eac..a67bd9b25840 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -44,6 +44,8 @@ jobs: outputs: gcp-variables-set: ${{ steps.check_gcp_variables.outputs.gcp-variables-set }} steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - uses: actions/checkout@v2 - name: "Check are GCP variables set" run: "./scripts/ci/ci_check_are_gcp_variables_set.sh" @@ -63,6 +65,8 @@ jobs: is_rc: ${{ steps.is_rc.outputs.is_rc }} rc_num: ${{ steps.get_rc_version.outputs.RC_NUM }} steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -350,6 +354,8 @@ jobs: timeout-minutes: 60 if: github.repository_owner == 'apache' && github.event_name == 'schedule' steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code on master branch uses: actions/checkout@v2 with: diff --git a/.github/workflows/cancel.yml b/.github/workflows/cancel.yml index c8b1ff895081..d00b36a2ebcb 100644 --- a/.github/workflows/cancel.yml +++ b/.github/workflows/cancel.yml @@ -30,6 +30,8 @@ jobs: name: "Cancel duplicate workflow runs" runs-on: self-hosted steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" uses: actions/checkout@v2 with: diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index ea9eb573e953..caf04d79bd3d 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -35,6 +35,8 @@ jobs: build: runs-on: self-hosted steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - uses: actions/checkout@v2 with: fetch-depth: 2 diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index abb828b54d9f..4d1267107cc9 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -46,6 +46,8 @@ jobs: outputs: gcp-variables-set: ${{ steps.check_gcp_variables.outputs.gcp-variables-set }} steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - uses: actions/checkout@v2 - name: "Check are GCP variables set" run: "./scripts/ci/ci_check_are_gcp_variables_set.sh" @@ -66,6 +68,9 @@ jobs: matrix: os: [self-hosted, macos-latest, windows-latest] steps: + - name: Clean GitHub workspace + if: startsWith(matrix.os, 'self') + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 with: @@ -125,6 +130,9 @@ jobs: matrix: os: [self-hosted, macos-latest, windows-latest] steps: + - name: Clean GitHub workspace + if: startsWith(matrix.os, 'self') + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 with: @@ -168,6 +176,9 @@ jobs: matrix: os: [self-hosted, macos-latest, windows-latest] steps: + - name: Clean GitHub workspace + if: startsWith(matrix.os, 'self') + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 with: diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index d8fdef9985b1..1d058651269f 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -34,6 +34,8 @@ jobs: name: "Self-hosted run local environment shell script" runs-on: self-hosted steps: + - name: Clean GitHub workspace + run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - uses: actions/checkout@v2 - name: "Installing local env dependencies" run: "sudo ./local-env-setup.sh" diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index e87bc179b8ae..ca13090b9c55 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -112,7 +112,7 @@ jobs: params: {"py_ver": "3.8", "tox_env": "py38"} steps: - name: Clean GitHub workspace - if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') + if: startsWith(matrix.os, 'self') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 @@ -160,7 +160,7 @@ jobs: python: 3.8 steps: - name: Clean GitHub workspace - if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') + if: startsWith(matrix.os, 'self') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Clean GitHub workspace Windows if: startsWith(matrix.os, 'windows') @@ -199,7 +199,7 @@ jobs: python: 3.8 steps: - name: Clean GitHub workspace - if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') + if: startsWith(matrix.os, 'self') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Clean GitHub workspace Windows if: startsWith(matrix.os, 'windows') From a5c3a5062ba7992a82c1ba4041b0dd74f273456d Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 5 Jan 2022 20:48:16 -0600 Subject: [PATCH 084/130] Included branch name to trigger all the workflows at the same time when pushing to it. --- .../Kubernetes/github-actions-hpa.yml | 4 ++-- .github/workflows/build_playground_backend.yml | 1 + .github/workflows/build_playground_frontend.yml | 1 + .github/workflows/build_wheels.yml | 2 +- .github/workflows/python_tests.yml | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml index b55cb09600a4..089c9dd84654 100644 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml @@ -24,6 +24,6 @@ spec: apiVersion: apps/v1 kind: Deployment name: github-actions-runners-deployment - minReplicas: 1 - maxReplicas: 10 + minReplicas: 5 + maxReplicas: 16 targetCPUUtilizationPercentage: 50 diff --git a/.github/workflows/build_playground_backend.yml b/.github/workflows/build_playground_backend.yml index 9576ed928d05..adfa5b662728 100644 --- a/.github/workflows/build_playground_backend.yml +++ b/.github/workflows/build_playground_backend.yml @@ -17,6 +17,7 @@ name: Build And Deploy Playground Backend Application on: push: + branches: ['beam-12812-githubactions'] tags: 'v*' pull_request: paths: ['playground/backend/**'] diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index 998c2218cbd8..12b39f12026e 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -18,6 +18,7 @@ name: Build And Deploy Playground Frontend Application on: push: tags: 'v*' + branches: ['beam-12812-githubactions'] pull_request: paths: ['playground/frontend/**'] workflow_dispatch: diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index a67bd9b25840..e395b746784c 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -23,7 +23,7 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*'] + branches: ['master', 'release-*', 'beam-12812-githubactions'] tags: 'v*' pull_request: branches: ['master', 'release-*'] diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index ca13090b9c55..db3eb8cd2114 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -23,7 +23,7 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*'] + branches: ['master', 'release-*', 'beam-12812-githubactions'] tags: 'v*' pull_request: branches: ['master', 'release-*'] From 0cd1abc7418d523d63310d6358e614d50c80202f Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 6 Jan 2022 09:58:05 -0600 Subject: [PATCH 085/130] Updated k8s deployment to increase the replicas to 5 --- .../Kubernetes/github-actions-deployment.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml index 3b64a40ad423..6469ca8952be 100644 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml @@ -25,7 +25,7 @@ spec: selector: matchLabels: name: github-actions - replicas: 2 + replicas: 5 template: metadata: labels: @@ -33,7 +33,7 @@ spec: spec: containers: - name: github-actions-runner - image: $IMAGE_URL:dev # replace variable manually + image: $IMAGE_URL:latest # replace variable manually securityContext: privileged: true envFrom: @@ -44,12 +44,12 @@ spec: mountPath: /var/run/docker.sock resources: requests: - memory: "1024Mi" + memory: "1028Mi" cpu: "2" - lifecycle: - preStop: - exec: - command: [./config.sh remove --token $GITHUB_TOKEN] # replace variable manually +# lifecycle: +# preStop: +# exec: +# command: [] volumes: - name: docker-sock hostPath: From 825bfe11e03192c8887ba170395648514e0f52e3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 10 Jan 2022 12:34:36 -0600 Subject: [PATCH 086/130] Updated hpa name to match linux pods. --- .../Kubernetes/github-actions-hpa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml index 089c9dd84654..472488a783fa 100644 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml +++ b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml @@ -18,7 +18,7 @@ apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: - name: hpa-github-actions + name: hpa-github-actions-linux spec: scaleTargetRef: apiVersion: apps/v1 From 19d403e77d17d88c87d4d441e51cb6978158a4ed Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 10 Jan 2022 13:06:50 -0600 Subject: [PATCH 087/130] Tox nodes set to 4. Removed Install tox windows step ib python_tests. --- .github/workflows/python_tests.yml | 4 ---- sdks/python/scripts/run_pytest.sh | 2 +- sdks/python/tox.ini | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index db3eb8cd2114..312edaae0625 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -123,12 +123,8 @@ jobs: - name: Get build dependencies working-directory: ./sdks/python run: pip install -r build-requirements.txt - - name: Install tox (Windows) - if: startsWith(matrix.os, 'windows') - run: pip install --upgrade pip tox virtualenv - name: Install tox run: pip install tox - if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') - name: Run tests basic unix if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') working-directory: ./sdks/python diff --git a/sdks/python/scripts/run_pytest.sh b/sdks/python/scripts/run_pytest.sh index dd12b2e92e4f..fff73eab4f86 100755 --- a/sdks/python/scripts/run_pytest.sh +++ b/sdks/python/scripts/run_pytest.sh @@ -37,7 +37,7 @@ fi # Run with pytest-xdist and without. pytest -o junit_suite_name=${envname} \ - --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 2 ${pytest_args} --pyargs ${posargs} + --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 4 ${pytest_args} --pyargs ${posargs} status1=$? pytest -o junit_suite_name=${envname}_no_xdist \ --junitxml=pytest_${envname}_no_xdist.xml -m 'no_xdist' ${pytest_args} --pyargs ${posargs} diff --git a/sdks/python/tox.ini b/sdks/python/tox.ini index 7a4b69850d41..a18fa91e965a 100644 --- a/sdks/python/tox.ini +++ b/sdks/python/tox.ini @@ -251,7 +251,7 @@ commands = /bin/sh -c "pip freeze | grep -E '(pyarrow|numpy)'" # Run pytest directly rather using run_pytest.sh. It doesn't handle # selecting tests with -m (BEAM-12985) - pytest -o junit_suite_name={envname} --junitxml=pytest_{envname}.xml -n 3 -m uses_pyarrow {posargs} + pytest -o junit_suite_name={envname} --junitxml=pytest_{envname}.xml -n 4 -m uses_pyarrow {posargs} [testenv:py{36,37,38}-pandas-{11,12,13}] deps = From 55c0c83be57ce0c7d264e3d8ab6555ff21b8729d Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 10 Jan 2022 15:18:17 -0600 Subject: [PATCH 088/130] Tox nodes set back to 6 --- sdks/python/scripts/run_pytest.sh | 2 +- sdks/python/tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/python/scripts/run_pytest.sh b/sdks/python/scripts/run_pytest.sh index fff73eab4f86..cd8b8b74c5dc 100755 --- a/sdks/python/scripts/run_pytest.sh +++ b/sdks/python/scripts/run_pytest.sh @@ -37,7 +37,7 @@ fi # Run with pytest-xdist and without. pytest -o junit_suite_name=${envname} \ - --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 4 ${pytest_args} --pyargs ${posargs} + --junitxml=pytest_${envname}.xml -m 'not no_xdist' -n 6 ${pytest_args} --pyargs ${posargs} status1=$? pytest -o junit_suite_name=${envname}_no_xdist \ --junitxml=pytest_${envname}_no_xdist.xml -m 'no_xdist' ${pytest_args} --pyargs ${posargs} diff --git a/sdks/python/tox.ini b/sdks/python/tox.ini index a18fa91e965a..54f079d89950 100644 --- a/sdks/python/tox.ini +++ b/sdks/python/tox.ini @@ -251,7 +251,7 @@ commands = /bin/sh -c "pip freeze | grep -E '(pyarrow|numpy)'" # Run pytest directly rather using run_pytest.sh. It doesn't handle # selecting tests with -m (BEAM-12985) - pytest -o junit_suite_name={envname} --junitxml=pytest_{envname}.xml -n 4 -m uses_pyarrow {posargs} + pytest -o junit_suite_name={envname} --junitxml=pytest_{envname}.xml -n 6 -m uses_pyarrow {posargs} [testenv:py{36,37,38}-pandas-{11,12,13}] deps = From eb14a679f862abe402cdfc07b10a4dc0bc624dd3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Mon, 10 Jan 2022 16:27:09 -0600 Subject: [PATCH 089/130] Updated aarch64 to run in self-hosted in build_wheels. --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index e395b746784c..d982ebf71f2d 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -217,7 +217,7 @@ jobs: ] arch: [auto] include: - - os_python: {"os": "ubuntu-latest", "python": "cp36-* cp37-* cp38-*"} + - os_python: {"os": "self-hosted", "python": "cp36-* cp37-* cp38-*"} arch: aarch64 steps: - name: Download python source distribution from artifacts From 1915deb99c9a02eaae078ef8b2deff8a6683c5b3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 17:27:53 -0600 Subject: [PATCH 090/130] Refactor folders and added README for self-hosted linux runners. --- .../self-hosted-linux/README.md | 74 +++++++++++++++++++ .../self-hosted-linux/docker}/Dockerfile | 0 .../docker}/docker-compose.yml | 2 +- .../self-hosted-linux/docker}/entrypoint.sh | 4 + .../self-hosted-linux/docker}/example.var.env | 0 .../kubernetes}/github-actions-deployment.yml | 4 - .../kubernetes}/github-actions-hpa.yml | 0 .../kubernetes}/github-actions-secrets.yml | 1 - .../kubernetes}/github-actions-vpa.yml | 0 .../kubernetes/run-k8s-deployment.sh | 20 +++++ .../Kubernetes/github-actions-pod-dind.yml | 46 ------------ 11 files changed, 99 insertions(+), 52 deletions(-) create mode 100644 .github/dockerized-gh-actions-runners/self-hosted-linux/README.md rename .github/{dockerized-gh_actions_runners => dockerized-gh-actions-runners/self-hosted-linux/docker}/Dockerfile (100%) rename .github/{dockerized-gh_actions_runners => dockerized-gh-actions-runners/self-hosted-linux/docker}/docker-compose.yml (96%) rename .github/{dockerized-gh_actions_runners => dockerized-gh-actions-runners/self-hosted-linux/docker}/entrypoint.sh (94%) rename .github/{dockerized-gh_actions_runners => dockerized-gh-actions-runners/self-hosted-linux/docker}/example.var.env (100%) rename .github/{dockerized-gh_actions_runners/Kubernetes => dockerized-gh-actions-runners/self-hosted-linux/kubernetes}/github-actions-deployment.yml (95%) rename .github/{dockerized-gh_actions_runners/Kubernetes => dockerized-gh-actions-runners/self-hosted-linux/kubernetes}/github-actions-hpa.yml (100%) rename .github/{dockerized-gh_actions_runners/Kubernetes => dockerized-gh-actions-runners/self-hosted-linux/kubernetes}/github-actions-secrets.yml (98%) rename .github/{dockerized-gh_actions_runners/Kubernetes => dockerized-gh-actions-runners/self-hosted-linux/kubernetes}/github-actions-vpa.yml (100%) create mode 100644 .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh delete mode 100644 .github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod-dind.yml diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/README.md b/.github/dockerized-gh-actions-runners/self-hosted-linux/README.md new file mode 100644 index 000000000000..0a5bf9b4c814 --- /dev/null +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/README.md @@ -0,0 +1,74 @@ + +# GitHub Actions - Self-hosted Linux Runners +These folders contain the required resources to deploy the GitHub Actions self-hosted runners for the workflows running in Ubuntu OS. +* /docker + * Dockerfile and entrypoint: Resources needed to create a new self-hosted-runner image. + * docker-compose.yml: In case you would like to test and run the self-hosted runner locally. + +* /kubernetes + * Kubernetes files to create the resources needed to deploy the sel-hosted runners. + +## Docker + +#### How to build a new image and push it to the Artifact Registry? +* Create the image locally + +`docker build -t $LOCAL_IMAGE_NAME:TAG .` + +* Tag the local image with the GCP repository name + +`docker tag $LOCAL_IMAGE_NAME LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE:latest` + +* Make sure you are authenticated to the gcloud repository + +`gcloud auth configure-docker us-central1-docker.pkg.dev` + +* Push the tagged image to the repository + +`docker push LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE:latest` + +#### How to run a self-hosted locally? + +* Create a `.var.env` file from the `example.var.env` file and replace the corresponding values + +* Run the container + +`docker-compose up` + +* You will be able to see the self-hosted runner in the Settings of your GitHub repository + +## Kubernetes +* Configure your Kubernetes local context + +`gcloud container clusters get-credentials $CLUSTER_NAME --zone us-central1-a --project $PROJECT-ID` + +* Update the `github-actions-secrets.yml` file with its corresponding encrypted in base64 values + +`echo $GITHUB_TOKEN | base64` +`echo GITHUB_REPO | base64` + +* Replace in `github-actions-deployment.yml` file the `$IMAGE_URL` variable with the corresponding image URL: `LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE` + +* In case you would like to create the deployment from scratch, run the `run-k8s-deployment.sh` script to do the Kubernetes deployment in the GKE cluster. Make sure you have the GKE context selected in your local machine + +`./run-k8s-deployment.sh` + +* Otherwise, apply only the changes. Make sure you have the GKE context selected in your local machine + +`kubectl apply -f github-actions-$FILE_NAME.yml` diff --git a/.github/dockerized-gh_actions_runners/Dockerfile b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile similarity index 100% rename from .github/dockerized-gh_actions_runners/Dockerfile rename to .github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile diff --git a/.github/dockerized-gh_actions_runners/docker-compose.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/docker-compose.yml similarity index 96% rename from .github/dockerized-gh_actions_runners/docker-compose.yml rename to .github/dockerized-gh-actions-runners/self-hosted-linux/docker/docker-compose.yml index e7032f46fa36..831caf9a722a 100644 --- a/.github/dockerized-gh_actions_runners/docker-compose.yml +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/docker-compose.yml @@ -21,7 +21,7 @@ services: runner: build: . entrypoint: ["/home/actions/entrypoint.sh"] - image: beam-ga:${TAG:-latest} + image: $IMAGE_URL:${TAG:-latest} volumes: - "/var/run/docker.sock:/var/run/docker.sock" env_file: diff --git a/.github/dockerized-gh_actions_runners/entrypoint.sh b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh similarity index 94% rename from .github/dockerized-gh_actions_runners/entrypoint.sh rename to .github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh index 9f1aedcbf7f9..eb3be7790cb4 100644 --- a/.github/dockerized-gh_actions_runners/entrypoint.sh +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh @@ -38,5 +38,9 @@ remove() { } trap 'remove; exit 130' INT trap 'remove; exit 143' TERM +trap 'remove; exit 143' QUIT +trap 'remove; exit 143' ABRT +trap 'remove; exit 0' EXIT + ./run.sh "$*" & wait $! diff --git a/.github/dockerized-gh_actions_runners/example.var.env b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env similarity index 100% rename from .github/dockerized-gh_actions_runners/example.var.env rename to .github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml similarity index 95% rename from .github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml rename to .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml index 6469ca8952be..653e2e7ce6b7 100644 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-deployment.yml +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml @@ -46,10 +46,6 @@ spec: requests: memory: "1028Mi" cpu: "2" -# lifecycle: -# preStop: -# exec: -# command: [] volumes: - name: docker-sock hostPath: diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml similarity index 100% rename from .github/dockerized-gh_actions_runners/Kubernetes/github-actions-hpa.yml rename to .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml similarity index 98% rename from .github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml rename to .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml index b1592e7a4b5c..5c3cc0251c21 100644 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-secrets.yml +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml @@ -24,4 +24,3 @@ type: Opaque data: GITHUB_TOKEN: GITHUB_REPO: - IMAGE_URL: \ No newline at end of file diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-vpa.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-vpa.yml similarity index 100% rename from .github/dockerized-gh_actions_runners/Kubernetes/github-actions-vpa.yml rename to .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-vpa.yml diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh new file mode 100644 index 000000000000..00260e831d50 --- /dev/null +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +kubectl apply -f github-actions-secrets.yml +kubectl apply -f github-actions-deployment.yml +kubectl apply -f github-actions-hpa.yml +kubectl apply -f github-actions-vpa.yml diff --git a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod-dind.yml b/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod-dind.yml deleted file mode 100644 index 28d5c74532d5..000000000000 --- a/.github/dockerized-gh_actions_runners/Kubernetes/github-actions-pod-dind.yml +++ /dev/null @@ -1,46 +0,0 @@ -################################################################################ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -################################################################################ - -apiVersion: v1 -kind: Pod -metadata: - name: pod-github-actions-dind - labels: - role: github-actions-role - name: github-actions -spec: - containers: - - name: github-actions-runner - image: $IMAGE_URL:dev #Replace $IMAGE_URL for the corresponding image url - envFrom: - - secretRef: - name: github-actions-secrets - env: - - name: DOCKER_HOST - value: tcp://localhost:2375 - - name: dind - image: docker:20.10-dind - securityContext: - privileged: true - volumeMounts: - - name: dind-storage - mountPath: /var/lib/docker - volumes: - - name: dind-storage - emptyDir: {} - From 84bd4fca7ec72ac04b4f39c8f860c1f2302abb6d Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 18:03:02 -0600 Subject: [PATCH 091/130] Added ubuntu-20.04 tag for self-hosted runs-on specification in workflows. --- .github/workflows/build_playground_backend.yml | 2 +- .github/workflows/build_playground_frontend.yml | 2 +- .github/workflows/build_wheels.yml | 14 +++++++------- .github/workflows/cancel.yml | 2 +- .github/workflows/go_tests.yml | 2 +- .github/workflows/java_tests.yml | 2 +- .github/workflows/local_env_tests.yml | 2 +- .github/workflows/python_tests.yml | 4 ++-- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build_playground_backend.yml b/.github/workflows/build_playground_backend.yml index adfa5b662728..af2138adb4c8 100644 --- a/.github/workflows/build_playground_backend.yml +++ b/.github/workflows/build_playground_backend.yml @@ -26,7 +26,7 @@ on: jobs: build_playground_backend_docker_image: name: Build Playground Backend App - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] env: GO_VERSION: 1.17.0 BEAM_VERSION: 2.33.0 diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index 12b39f12026e..36724c4ec5bf 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -26,7 +26,7 @@ on: jobs: build_playground_frontend_docker_image: name: Build Playground Frontend App - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] env: GO_VERSION: 1.17.0 BEAM_VERSION: 2.33.0 diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index d982ebf71f2d..696d7240ddf7 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -40,7 +40,7 @@ jobs: check_gcp_variables: timeout-minutes: 5 name: "Check GCP variables" - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] outputs: gcp-variables-set: ${{ steps.check_gcp_variables.outputs.gcp-variables-set }} steps: @@ -59,7 +59,7 @@ jobs: GCP_TESTING_BUCKET: "not-needed-here" build_source: - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] name: Build python source distribution outputs: is_rc: ${{ steps.is_rc.outputs.is_rc }} @@ -170,7 +170,7 @@ jobs: needs: - build_source - check_gcp_variables - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' steps: - name: Authenticate on GCP @@ -186,7 +186,7 @@ jobs: needs: - prepare_gcs - check_gcp_variables - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' steps: - name: Download compressed sources from artifacts @@ -290,7 +290,7 @@ jobs: needs: - build_wheels - check_gcp_variables - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: @@ -334,7 +334,7 @@ jobs: needs: - upload_wheels_to_gcs - check_gcp_variables - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' steps: - name: Authenticate on GCP @@ -350,7 +350,7 @@ jobs: needs: - build_source - build_wheels - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] timeout-minutes: 60 if: github.repository_owner == 'apache' && github.event_name == 'schedule' steps: diff --git a/.github/workflows/cancel.yml b/.github/workflows/cancel.yml index d00b36a2ebcb..76d234a3c7ee 100644 --- a/.github/workflows/cancel.yml +++ b/.github/workflows/cancel.yml @@ -28,7 +28,7 @@ on: jobs: cancel-duplicate-workflow-runs: name: "Cancel duplicate workflow runs" - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] steps: - name: Clean GitHub workspace run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index caf04d79bd3d..5646ab2db9ab 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -33,7 +33,7 @@ on: jobs: build: - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] steps: - name: Clean GitHub workspace run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 4d1267107cc9..c1c36d0430c5 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -42,7 +42,7 @@ jobs: check_gcp_variables: timeout-minutes: 5 name: "Check GCP variables set" - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] outputs: gcp-variables-set: ${{ steps.check_gcp_variables.outputs.gcp-variables-set }} steps: diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index 1d058651269f..12ea5a81ac52 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -32,7 +32,7 @@ jobs: run_local_env_install_ubuntu: timeout-minutes: 25 name: "Self-hosted run local environment shell script" - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] steps: - name: Clean GitHub workspace run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 312edaae0625..17e0303f04ca 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -41,7 +41,7 @@ jobs: check_gcp_variables: timeout-minutes: 5 name: "Check GCP variables" - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] outputs: gcp-variables-set: ${{ steps.check_gcp_variables.outputs.gcp-variables-set }} steps: @@ -68,7 +68,7 @@ jobs: ) needs: - check_gcp_variables - runs-on: self-hosted + runs-on: [self-hosted, ubuntu-20.04] steps: - name: Clean GitHub workspace run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi From f44d95dad29ce68e3e1eabf269b2c8fac9eaac74 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 18:32:28 -0600 Subject: [PATCH 092/130] Added ubuntu-20.04 tag for matrix self-hosted runs-on specification in java, python and build_wheels workflows. --- .github/workflows/build_wheels.yml | 2 +- .github/workflows/java_tests.yml | 6 +++--- .github/workflows/python_tests.yml | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 696d7240ddf7..9f599ba5e59b 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -211,7 +211,7 @@ jobs: strategy: matrix: os_python: [ - {"os": "self-hosted", "python": "cp36-* cp37-* cp38-*"}, + {"os": [self-hosted, ubuntu-20.04], "python": "cp36-* cp37-* cp38-*"}, {"os": "macos-latest", "python": "cp36-* cp37-* cp38-*"}, {"os": "windows-latest", "python": "cp36-* cp37-* cp38-*"}, ] diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index c1c36d0430c5..d7650c22e130 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -66,7 +66,7 @@ jobs: strategy: fail-fast: false matrix: - os: [self-hosted, macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') @@ -128,7 +128,7 @@ jobs: strategy: fail-fast: false matrix: - os: [self-hosted, macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') @@ -174,7 +174,7 @@ jobs: strategy: fail-fast: false matrix: - os: [self-hosted, macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] steps: - name: Clean GitHub workspace if: startsWith(matrix.os, 'self') diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 17e0303f04ca..9434bb540c9c 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -99,7 +99,7 @@ jobs: strategy: fail-fast: false matrix: - os: [self-hosted, macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, @@ -147,7 +147,7 @@ jobs: strategy: fail-fast: false matrix: - os: [self-hosted, macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved @@ -186,7 +186,7 @@ jobs: strategy: fail-fast: false matrix: - os: [self-hosted, macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] python: [3.6, 3.7, 3.8] exclude: # TODO remove exclusion after issue with protobuf is solved From cec02836708a467861c8c6488aae80da1952dc34 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 18:45:38 -0600 Subject: [PATCH 093/130] Replaced startsWith condition to contains to check if the Array has the tag ubuntu-20.04. --- .github/workflows/java_tests.yml | 6 +++--- .github/workflows/python_tests.yml | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index d7650c22e130..0725354e374e 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -69,7 +69,7 @@ jobs: os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] steps: - name: Clean GitHub workspace - if: startsWith(matrix.os, 'self') + if: contains(matrix.os, 'ubuntu-20.04') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 @@ -131,7 +131,7 @@ jobs: os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] steps: - name: Clean GitHub workspace - if: startsWith(matrix.os, 'self') + if: contains(matrix.os, 'ubuntu-20.04') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 @@ -177,7 +177,7 @@ jobs: os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] steps: - name: Clean GitHub workspace - if: startsWith(matrix.os, 'self') + if: contains(matrix.os, 'ubuntu-20.04') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 9434bb540c9c..bfbf072334f2 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -112,7 +112,7 @@ jobs: params: {"py_ver": "3.8", "tox_env": "py38"} steps: - name: Clean GitHub workspace - if: startsWith(matrix.os, 'self') + if: contains(matrix.os, 'ubuntu-20.04') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Checkout code uses: actions/checkout@v2 @@ -126,7 +126,7 @@ jobs: - name: Install tox run: pip install tox - name: Run tests basic unix - if: startsWith(matrix.os, 'self') || startsWith(matrix.os, 'macos') + if: contains(matrix.os, 'ubuntu-20.04') || startsWith(matrix.os, 'macos') working-directory: ./sdks/python run: tox -c tox.ini -e ${{ matrix.params.tox_env }} # Commented by the moment to run memory&cpu resources. @@ -156,7 +156,7 @@ jobs: python: 3.8 steps: - name: Clean GitHub workspace - if: startsWith(matrix.os, 'self') + if: contains(matrix.os, 'ubuntu-20.04') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Clean GitHub workspace Windows if: startsWith(matrix.os, 'windows') @@ -195,7 +195,7 @@ jobs: python: 3.8 steps: - name: Clean GitHub workspace - if: startsWith(matrix.os, 'self') + if: contains(matrix.os, 'ubuntu-20.04') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Clean GitHub workspace Windows if: startsWith(matrix.os, 'windows') From 388e2edb79107b95afb109725aad4e0499a8afc7 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 18:58:56 -0600 Subject: [PATCH 094/130] Updated build_wheels name to display the tags in the step name. --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 9f599ba5e59b..933437b31194 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,7 +203,7 @@ jobs: run: gsutil cp -r -a public-read source/* ${{ env.GCP_PATH }} build_wheels: - name: Build python wheels on ${{matrix.arch}} for ${{ matrix.os_python.os }} + name: Build python wheels on ${{matrix.arch}} for ${{ fromJSON(matrix.os_python.os) }} needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} From cf86bbeb7990248de78e80c6ec970446db15dc67 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 19:03:48 -0600 Subject: [PATCH 095/130] Updated build_wheels name to display the tags in the step name fromJSON. --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 933437b31194..9064a398c460 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,7 +203,7 @@ jobs: run: gsutil cp -r -a public-read source/* ${{ env.GCP_PATH }} build_wheels: - name: Build python wheels on ${{matrix.arch}} for ${{ fromJSON(matrix.os_python.os) }} + name: Build python wheels on ${{matrix.arch}} for ${{ fromJSON(matrix.os_python) }} needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} From 7c33e03f169e1742588f7fd7399fb72933efa02f Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 19:06:46 -0600 Subject: [PATCH 096/130] Updated name in build_wheels to display ad filter the matrix os. --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 9064a398c460..5641869a5e18 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,7 +203,7 @@ jobs: run: gsutil cp -r -a public-read source/* ${{ env.GCP_PATH }} build_wheels: - name: Build python wheels on ${{matrix.arch}} for ${{ fromJSON(matrix.os_python) }} + name: Build python wheels on ${{matrix.arch}} for ${{ matrix.os_python.*.os }} needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} From 0af0b8b1f6d77c3377801bf68d9173a61ef091f3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 19:21:48 -0600 Subject: [PATCH 097/130] Updated matrix values to have an array in build_wheels --- .github/workflows/build_wheels.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 5641869a5e18..c2f309eedee5 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,7 +203,7 @@ jobs: run: gsutil cp -r -a public-read source/* ${{ env.GCP_PATH }} build_wheels: - name: Build python wheels on ${{matrix.arch}} for ${{ matrix.os_python.*.os }} + name: Build python wheels on ${{matrix.arch}} for ${{ matrix.os_python.os[0}} needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} @@ -212,8 +212,8 @@ jobs: matrix: os_python: [ {"os": [self-hosted, ubuntu-20.04], "python": "cp36-* cp37-* cp38-*"}, - {"os": "macos-latest", "python": "cp36-* cp37-* cp38-*"}, - {"os": "windows-latest", "python": "cp36-* cp37-* cp38-*"}, + {"os": [macos-latest], "python": "cp36-* cp37-* cp38-*"}, + {"os": [windows-latest], "python": "cp36-* cp37-* cp38-*"}, ] arch: [auto] include: From 7541ce131fbb2bc0e71e00978f9704a6196e02b6 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 19:23:19 -0600 Subject: [PATCH 098/130] Fixed syntax issue in matrix values to have an array in build_wheels --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index c2f309eedee5..33dad085cb83 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,7 +203,7 @@ jobs: run: gsutil cp -r -a public-read source/* ${{ env.GCP_PATH }} build_wheels: - name: Build python wheels on ${{matrix.arch}} for ${{ matrix.os_python.os[0}} + name: Build python wheels on ${{matrix.arch}} for ${{ matrix.os_python.os[0]}} needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} From 4996e2760053144d3dd1d3492d981180c7eac954 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 19:32:52 -0600 Subject: [PATCH 099/130] Join matrix name to display it correctly in the Step name. --- .github/workflows/build_wheels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 33dad085cb83..59627247c29f 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,7 +203,7 @@ jobs: run: gsutil cp -r -a public-read source/* ${{ env.GCP_PATH }} build_wheels: - name: Build python wheels on ${{matrix.arch}} for ${{ matrix.os_python.os[0]}} + name: Build python wheels on ${{matrix.arch}} for ${{ join(matrix.os_python.os, ', ')}} needs: build_source env: CIBW_ARCHS_LINUX: ${{matrix.arch}} @@ -217,7 +217,7 @@ jobs: ] arch: [auto] include: - - os_python: {"os": "self-hosted", "python": "cp36-* cp37-* cp38-*"} + - os_python: {"os": [self-hosted, ubuntu-20.04], "python": "cp36-* cp37-* cp38-*"} arch: aarch64 steps: - name: Download python source distribution from artifacts From 89f0d6b4a33af4efc4e25c1b536abf564118c593 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Tue, 11 Jan 2022 19:39:01 -0600 Subject: [PATCH 100/130] Added empty lines at the end of the files to avoid possible issues. --- .../self-hosted-linux/docker/docker-compose.yml | 2 +- .../self-hosted-linux/docker/example.var.env | 2 +- .github/workflows/go_tests.yml | 2 +- .github/workflows/java_tests.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/docker-compose.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/docker-compose.yml index 831caf9a722a..8d1f7e7ad134 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/docker-compose.yml +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/docker-compose.yml @@ -25,4 +25,4 @@ services: volumes: - "/var/run/docker.sock:/var/run/docker.sock" env_file: - - ./var.env \ No newline at end of file + - ./var.env diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env index 0ee67cd4f47b..f3c31d3ece80 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env @@ -1,3 +1,3 @@ # var.env example, please create a var.env file with the corresponding values of the variables GITHUB_TOKEN= -GITHUB_REPO= \ No newline at end of file +GITHUB_REPO= diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index 5646ab2db9ab..74ee79125a35 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -48,4 +48,4 @@ jobs: - name: Run coverage run: cd sdks/go/pkg && go test -coverprofile=coverage.txt -covermode=atomic ./... - name: Upload to codecov - run: bash <(curl -s https://codecov.io/bash) \ No newline at end of file + run: bash <(curl -s https://codecov.io/bash) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 0725354e374e..9fa05b32d340 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -212,4 +212,4 @@ jobs: if: always() with: name: java_wordcount_dataflow-${{matrix.os}} - path: examples/java/build/reports/tests/integrationTest \ No newline at end of file + path: examples/java/build/reports/tests/integrationTest From 525c225e866d4e293370626be0b82c1f470c80cd Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 12 Jan 2022 11:34:53 -0600 Subject: [PATCH 101/130] Removed Clean GitHub workspace for windows TODO step. --- .github/workflows/build_wheels.yml | 2 +- .github/workflows/python_tests.yml | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 59627247c29f..5296ef6af6b7 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -294,7 +294,7 @@ jobs: if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: - os : [self-hosted, macos-latest, windows-latest] + os : [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] steps: - name: Download wheels from artifacts uses: actions/download-artifact@v2 diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index bfbf072334f2..83948b2acffd 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -158,9 +158,6 @@ jobs: - name: Clean GitHub workspace if: contains(matrix.os, 'ubuntu-20.04') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - - name: Clean GitHub workspace Windows - if: startsWith(matrix.os, 'windows') - run: echo TODO commands to clean workspace in self-hosted-windows - name: Checkout code uses: actions/checkout@v2 - name: Install python @@ -197,9 +194,6 @@ jobs: - name: Clean GitHub workspace if: contains(matrix.os, 'ubuntu-20.04') run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - - name: Clean GitHub workspace Windows - if: startsWith(matrix.os, 'windows') - run: echo TODO commands to clean workspace in self-hosted-windows - name: Checkout code uses: actions/checkout@v2 - name: Install python From 684cbbba7c3bcd7ced80e8328ffaf8cebfa19a6a Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 12 Jan 2022 13:45:16 -0600 Subject: [PATCH 102/130] Reduced maxReplicas in HorziontalPodAutoscaler yml file. --- .../self-hosted-linux/kubernetes/github-actions-hpa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml index 472488a783fa..1ace3af0a1ea 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml @@ -25,5 +25,5 @@ spec: kind: Deployment name: github-actions-runners-deployment minReplicas: 5 - maxReplicas: 16 + maxReplicas: 12 targetCPUUtilizationPercentage: 50 From ee007345dd72de99acef4589339f5feb990676ec Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 12 Jan 2022 16:18:55 -0600 Subject: [PATCH 103/130] Updated github-actions version in Dockerfile. Added enable-vertical-pod-autoscaling command in run k8s script --- .../self-hosted-linux/docker/Dockerfile | 2 +- .../self-hosted-linux/kubernetes/run-k8s-deployment.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 100755 .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile index f8cd8d806f52..4cfa1e327db4 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile @@ -18,7 +18,7 @@ FROM ubuntu:20.04 -ARG RUNNER_VERSION=2.285.1 +ARG RUNNER_VERSION=2.286.0 RUN apt-get -yqq update #Install APT packages diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh old mode 100644 new mode 100755 index 00260e831d50..06a4e1c2da0b --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh @@ -17,4 +17,5 @@ kubectl apply -f github-actions-secrets.yml kubectl apply -f github-actions-deployment.yml kubectl apply -f github-actions-hpa.yml +gcloud container clusters update github-actions-linux-runners --enable-vertical-pod-autoscaling --zone us-central1-a kubectl apply -f github-actions-vpa.yml From a6b811b66a93e6d539ae4c08e86728d2b368f9dd Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 09:54:12 -0600 Subject: [PATCH 104/130] Included master changes in build_playground_frontend.yml file. --- .../workflows/build_playground_frontend.yml | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index 36724c4ec5bf..abcafc179a9c 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -36,9 +36,10 @@ jobs: run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Check out the repo uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: joschi/setup-jdk@v2 + - name: Install Java + uses: actions/setup-java@v2 with: + distribution: 'zulu' java-version: '8' - name: install flutter uses: subosito/flutter-action@v1 @@ -65,12 +66,28 @@ jobs: - name: Login to Docker Registry run: cat /tmp/gcp_access.json | docker login -u _json_key --password-stdin https://${{ secrets.REGISTRY_NAME }} if: startsWith(github.ref, 'ref/tags/') - - name: Preapre Build + - name: Preapre Build Java run: ./gradlew --debug playground:frontend:dockerPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' if: startsWith(github.ref, 'ref/tags/') - - name: Deploy Backend Application + - name: Preapre Build Python + run: ./gradlew playground:backend:containers:python:dockerPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pbase-image='apache/beam_java8_sdk:${{ env.BEAM_VERSION }}' + - name: Preapre Build Go + run: ./gradlew playground:backend:containers:go:dockerPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pbase-image='apache/beam_java8_sdk:${{ env.BEAM_VERSION }}' + if: startsWith(github.ref, 'ref/tags/') + - name: Deploy Backend Application Java env: GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json run: terraform init && terraform apply -auto-approve -var="project_id=${{ secrets.PROJECT_ID }}" -var="docker_registry_address=${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository" working-directory: playground/terraform/applications/backend if: startsWith(github.ref, 'ref/tags/') + - name: Deploy Backend Application Python + env: + GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json + run: terraform init && terraform apply -auto-approve -var="project_id=${{ secrets.PROJECT_ID }}" -var="docker_registry_address=${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository" + working-directory: playground/terraform/applications/backend-python + - name: Deploy Backend Application Go + env: + GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json + run: terraform init && terraform apply -auto-approve -var="project_id=${{ secrets.PROJECT_ID }}" -var="docker_registry_address=${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository" + working-directory: playground/terraform/applications/backend-go + if: startsWith(github.ref, 'ref/tags/') From 25084b78b9ea9270277a8d7d609b2b64672c7adc Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 10:39:01 -0600 Subject: [PATCH 105/130] Reverted build_playground_frontend.yml file changes --- .../workflows/build_playground_frontend.yml | 35 +++++-------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index abcafc179a9c..1b092e78410c 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -36,21 +36,20 @@ jobs: run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Check out the repo uses: actions/checkout@v2 - - name: Install Java - uses: actions/setup-java@v2 + - name: Set up JDK 1.8 + uses: joschi/setup-jdk@v2 with: - distribution: 'zulu' - java-version: '8' + java-version: '8' - name: install flutter uses: subosito/flutter-action@v1 with: - channel: 'stable' + channel: 'stable' - name: Run PreCommit run: ./gradlew playground:frontend:precommit - name: install npm uses: actions/setup-node@v2 with: - node-version: '14' + node-version: '14' - name: install docker linter run: npm install -g dockerlint - name: lint dockerfile @@ -58,7 +57,7 @@ jobs: working-directory: playground/frontend - uses: hashicorp/setup-terraform@v1 with: - terraform_version: ${{ env.TERRAFORM_VERSION }} + terraform_version: ${{ env.TERRAFORM_VERSION }} if: startsWith(github.ref, 'ref/tags/') - name: Setup GCP account run: echo ${{ secrets.GCP_ACCESS_KEY }} | base64 -d > /tmp/gcp_access.json @@ -66,28 +65,12 @@ jobs: - name: Login to Docker Registry run: cat /tmp/gcp_access.json | docker login -u _json_key --password-stdin https://${{ secrets.REGISTRY_NAME }} if: startsWith(github.ref, 'ref/tags/') - - name: Preapre Build Java + - name: Preapre Build run: ./gradlew --debug playground:frontend:dockerPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' if: startsWith(github.ref, 'ref/tags/') - - name: Preapre Build Python - run: ./gradlew playground:backend:containers:python:dockerPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pbase-image='apache/beam_java8_sdk:${{ env.BEAM_VERSION }}' - - name: Preapre Build Go - run: ./gradlew playground:backend:containers:go:dockerPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pbase-image='apache/beam_java8_sdk:${{ env.BEAM_VERSION }}' - if: startsWith(github.ref, 'ref/tags/') - - name: Deploy Backend Application Java + - name: Deploy Backend Application env: GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json run: terraform init && terraform apply -auto-approve -var="project_id=${{ secrets.PROJECT_ID }}" -var="docker_registry_address=${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository" working-directory: playground/terraform/applications/backend - if: startsWith(github.ref, 'ref/tags/') - - name: Deploy Backend Application Python - env: - GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json - run: terraform init && terraform apply -auto-approve -var="project_id=${{ secrets.PROJECT_ID }}" -var="docker_registry_address=${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository" - working-directory: playground/terraform/applications/backend-python - - name: Deploy Backend Application Go - env: - GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json - run: terraform init && terraform apply -auto-approve -var="project_id=${{ secrets.PROJECT_ID }}" -var="docker_registry_address=${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository" - working-directory: playground/terraform/applications/backend-go - if: startsWith(github.ref, 'ref/tags/') + if: startsWith(github.ref, 'ref/tags/') \ No newline at end of file From c51eb296bc3883fb0c1873ed6ccbd77e6f0c204f Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 10:53:54 -0600 Subject: [PATCH 106/130] Included master changes in build_playground_backend.yml to get the latest changes. --- .../workflows/build_playground_backend.yml | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_playground_backend.yml b/.github/workflows/build_playground_backend.yml index af2138adb4c8..cd5e64fd11d0 100644 --- a/.github/workflows/build_playground_backend.yml +++ b/.github/workflows/build_playground_backend.yml @@ -18,7 +18,7 @@ name: Build And Deploy Playground Backend Application on: push: branches: ['beam-12812-githubactions'] - tags: 'v*' + tags: ['v*'] pull_request: paths: ['playground/backend/**'] workflow_dispatch: @@ -36,9 +36,10 @@ jobs: run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Check out the repo uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: joschi/setup-jdk@v2 + - name: Install Java + uses: actions/setup-java@v2 with: + distribution: 'zulu' java-version: '8' - uses: actions/setup-go@v2 with: @@ -69,12 +70,29 @@ jobs: - name: Login to Docker Registry run: cat /tmp/gcp_access.json | docker login -u _json_key --password-stdin https://${{ secrets.REGISTRY_NAME }} if: startsWith(github.ref, 'ref/tags/') - - name: Preapre Build + - name: Preapre Build Java run: ./gradlew playground:backend:containers:java:dockerPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pbase-image='apache/beam_java8_sdk:${{ env.BEAM_VERSION }}' if: startsWith(github.ref, 'ref/tags/') - - name: Deploy Backend Application + - name: Preapre Build Python + run: ./gradlew playground:backend:containers:python:dockerPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pbase-image='apache/beam_java8_sdk:${{ env.BEAM_VERSION }}' + - name: Preapre Build Go + run: ./gradlew playground:backend:containers:go:dockerPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pbase-image='apache/beam_java8_sdk:${{ env.BEAM_VERSION }}' + if: startsWith(github.ref, 'ref/tags/') + - name: Deploy Backend Application Java env: GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json run: terraform init && terraform apply -auto-approve -var="project_id=${{ secrets.PROJECT_ID }}" -var="docker_registry_address=${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository" working-directory: playground/terraform/applications/backend if: startsWith(github.ref, 'ref/tags/') + - name: Deploy Backend Application Python + env: + GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json + run: terraform init && terraform apply -auto-approve -var="project_id=${{ secrets.PROJECT_ID }}" -var="docker_registry_address=${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository" + working-directory: playground/terraform/applications/backend-python + - name: Deploy Backend Application Go + env: + GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json + run: terraform init && terraform apply -auto-approve -var="project_id=${{ secrets.PROJECT_ID }}" -var="docker_registry_address=${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository" + working-directory: playground/terraform/applications/backend-go + if: startsWith(github.ref, 'ref/tags/') + From 698b141e1816423ade9faaa5a1532b5a1f492143 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 11:10:13 -0600 Subject: [PATCH 107/130] Included master changes in build_playground_frontend.yml to get the latest changes. --- .../workflows/build_playground_frontend.yml | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index 1b092e78410c..c434040f95f5 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -17,7 +17,7 @@ name: Build And Deploy Playground Frontend Application on: push: - tags: 'v*' + tags: ['v*'] branches: ['beam-12812-githubactions'] pull_request: paths: ['playground/frontend/**'] @@ -31,19 +31,29 @@ jobs: GO_VERSION: 1.17.0 BEAM_VERSION: 2.33.0 TERRAFORM_VERSION: 1.0.9 + FLUTTER_VERSION: 2.5.2-stable steps: - name: Clean GitHub workspace run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Check out the repo uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: joschi/setup-jdk@v2 + - name: Setup Java + uses: actions/setup-java@v2 with: + distribution: 'zulu' java-version: '8' - - name: install flutter - uses: subosito/flutter-action@v1 - with: - channel: 'stable' + - name: Install Flutter + run: | + wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_$FLUTTER_VERSION.tar.xz &&\ + tar -xf flutter_linux_$FLUTTER_VERSION.tar.xz &&\ + mv flutter /opt/ &&\ + ln -s /opt/flutter/bin/flutter /usr/local/bin/flutter &&\ + ln -s /opt/flutter/bin/dart /usr/local/bin/dart &&\ + dart pub global activate protoc_plugin &&\ + ln -s /root/.pub-cache/bin/protoc-gen-dart /usr/local/bin/ + - name: Remove default github maven configuration + # This step is a workaround to avoid a decryption issue + run: rm ~/.m2/settings.xml - name: Run PreCommit run: ./gradlew playground:frontend:precommit - name: install npm From 51b228a8cbceaf9f0c28ec8fac8af33d049d2bd0 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 11:14:51 -0600 Subject: [PATCH 108/130] Added privileges to run commands in build_playground_frontend workflow --- .github/workflows/build_playground_frontend.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index c434040f95f5..27c81d214cae 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -46,14 +46,14 @@ jobs: run: | wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_$FLUTTER_VERSION.tar.xz &&\ tar -xf flutter_linux_$FLUTTER_VERSION.tar.xz &&\ - mv flutter /opt/ &&\ - ln -s /opt/flutter/bin/flutter /usr/local/bin/flutter &&\ - ln -s /opt/flutter/bin/dart /usr/local/bin/dart &&\ - dart pub global activate protoc_plugin &&\ - ln -s /root/.pub-cache/bin/protoc-gen-dart /usr/local/bin/ + sudo mv flutter /opt/ &&\ + sudo ln -s /opt/flutter/bin/flutter /usr/local/bin/flutter &&\ + sudo ln -s /opt/flutter/bin/dart /usr/local/bin/dart &&\ + sudo dart pub global activate protoc_plugin &&\ + sudo ln -s /root/.pub-cache/bin/protoc-gen-dart /usr/local/bin/ - name: Remove default github maven configuration # This step is a workaround to avoid a decryption issue - run: rm ~/.m2/settings.xml + run: sudo rm ~/.m2/settings.xml - name: Run PreCommit run: ./gradlew playground:frontend:precommit - name: install npm From 9239fe51c6b45a5fb0b7a87cf632ac1ebbadd7d1 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 11:28:24 -0600 Subject: [PATCH 109/130] Included master changes in java_tests file to get the latest setup go changes. --- .github/workflows/java_tests.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 9fa05b32d340..40fc8343b74e 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -29,16 +29,23 @@ on: - cron: '10 2 * * *' push: branches: ['master', 'release-*', 'beam-12812-githubactions'] - tags: 'v*' + tags: ['v*'] pull_request: branches: ['master', 'release-*'] - tags: 'v*' + tags: ['v*'] paths: ['sdks/java/**', 'model/**', 'runners/**', 'examples/java/**', 'examples/kotlin/**', 'release/**', 'buildSrc/**'] jobs: - + setup-go: + name: "Set up Go" + runs-on: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest ] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: '1.16.12' check_gcp_variables: timeout-minutes: 5 name: "Check GCP variables set" @@ -123,6 +130,7 @@ jobs: path: runners/core-java/build/reports/tests/test java_wordcount_direct_runner: + needs: setup-go name: 'Java Wordcount Direct Runner' runs-on: ${{ matrix.os }} strategy: @@ -165,6 +173,7 @@ jobs: name: 'Java Wordcount Dataflow' needs: - check_gcp_variables + - setup-go runs-on: ${{ matrix.os }} if: | needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && ( From ecdc207ccb2f0b676c3679d01778e44c2c10c332 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 11:31:57 -0600 Subject: [PATCH 110/130] Updated set up go step to include the matrix.os runs-on in java_tests --- .github/workflows/java_tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 40fc8343b74e..3dd49d7970bb 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -40,7 +40,11 @@ on: jobs: setup-go: name: "Set up Go" - runs-on: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest ] + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ [ self-hosted, ubuntu-20.04 ], macos-latest, windows-latest ] steps: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 From ecc2545e9102e051102ef90dde4bafc772803f38 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 12:39:18 -0600 Subject: [PATCH 111/130] Added playground_deploy_examples.yml from master branch and updated the runs-on to self-hosted. --- .../workflows/build_playground_frontend.yml | 1 - .github/workflows/build_wheels.yml | 2 +- .../workflows/playground_deploy_examples.yml | 130 ++++++++++++++++++ .github/workflows/python_tests.yml | 2 +- 4 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/playground_deploy_examples.yml diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index 27c81d214cae..be7bf971e360 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -18,7 +18,6 @@ name: Build And Deploy Playground Frontend Application on: push: tags: ['v*'] - branches: ['beam-12812-githubactions'] pull_request: paths: ['playground/frontend/**'] workflow_dispatch: diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 5296ef6af6b7..6bf2beeefbb4 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -23,7 +23,7 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*', 'beam-12812-githubactions'] + branches: ['master', 'release-*'] tags: 'v*' pull_request: branches: ['master', 'release-*'] diff --git a/.github/workflows/playground_deploy_examples.yml b/.github/workflows/playground_deploy_examples.yml new file mode 100644 index 000000000000..b124e3eac398 --- /dev/null +++ b/.github/workflows/playground_deploy_examples.yml @@ -0,0 +1,130 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Collect And Deploy Playground Examples + +on: + push: + branches: ['beam-12812-githubactions'] + tags: ['v*'] + workflow_dispatch: + +jobs: + deploy_examples: + name: Deploy examples + runs-on: [self-hosted, ubuntu-20.04] + env: + BEAM_ROOT_DIR: ../../ + BEAM_EXAMPLE_CATEGORIES: ../categories.yaml + BEAM_VERSION: 2.33.0 + SERVER_ADDRESS: backend-python-dot-datatokenization.uc.r.appspot.com + K8S_NAMESPACE: playground-backend + HELM_APP_NAME: playground-backend + steps: + - name: Check out the repo + uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.8' + - uses: actions/setup-java@v2 + with: + distribution: 'zulu' + java-version: '8' + - name: Install kubectl + run: | + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" &&\ + chmod +x kubectl &&\ + mv kubectl /usr/local/bin/ + - name: Install helm + run: | + curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 &&\ + chmod 700 get_helm.sh &&\ + ./get_helm.sh + - name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@v0.3.0 + - name: install deps + run: pip install -r requirements.txt + working-directory: playground/infrastructure + - name: Setup GCP account + run: | + echo "${{ secrets.GCP_ACCESS_KEY }}" | base64 -d > /tmp/gcp_access.json + gcloud auth activate-service-account --project=datatokenization --key-file=/tmp/gcp_access.json + - name: Get K8s Config + run: gcloud container clusters get-credentials --region us-central1-a playground-examples + - name: Login to Docker Registry + run: cat /tmp/gcp_access.json | docker login -u _json_key --password-stdin https://${{ secrets.REGISTRY_NAME }} + - name: Build And Push Java Backend + run: ./gradlew playground:backend:containers:java:dockerTagPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pbase-image='apache/beam_java8_sdk:${{ env.BEAM_VERSION }}' -Pdocker-tag="$GITHUB_SHA" + - name: Build And Push Go Backend + run: ./gradlew playground:backend:containers:go:dockerTagPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pdocker-tag="$GITHUB_SHA" + - name: Build And Push Python Backend + run: ./gradlew playground:backend:containers:python:dockerTagPush -Pdocker-repository-root='${{ secrets.REGISTRY_NAME}}/${{ secrets.PROJECT_ID }}/playground-repository' -Pdocker-tag="$GITHUB_SHA" + - name: Install helm chart + run: | + kubectl create namespace $K8S_NAMESPACE --dry-run=client -o yaml | kubectl apply -f - &&\ + helm install --namespace $K8S_NAMESPACE $HELM_APP_NAME . --set global.registry="${{ secrets.REGISTRY_NAME }}/${{ secrets.PROJECT_ID }}/playground-repository" --set global.tag="$GITHUB_SHA" &&\ + sleep 120 + working-directory: playground/infrastructure/helm + - name: Run Python Examples CI + run: | + K8S_SERVER_ADDRESS=$(kubectl get svc -n $K8S_NAMESPACE -l "app=service-python" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') + BEAM_ROOT_DIR="../../" + BEAM_EXAMPLE_CATEGORIES="../../playground/categories.yaml" + export SERVER_ADDRESS="$K8S_SERVER_ADDRESS:8081" && python3 ci_cd.py --step CI --sdk SDK_PYTHON + working-directory: playground/infrastructure + - name: Run Python Examples CD + run: | + K8S_SERVER_ADDRESS=$(kubectl get svc -n $K8S_NAMESPACE -l "app=service-python" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') + BEAM_ROOT_DIR="../../" + BEAM_EXAMPLE_CATEGORIES="../../playground/categories.yaml" + export SERVER_ADDRESS="$K8S_SERVER_ADDRESS:8081" && python3 ci_cd.py --step CD --sdk SDK_PYTHON + working-directory: playground/infrastructure + env: + GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json + - name: Run Go Examples CI + run: | + K8S_SERVER_ADDRESS=$(kubectl get svc -n $K8S_NAMESPACE -l "app=service-go" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') + BEAM_ROOT_DIR="../../" + BEAM_EXAMPLE_CATEGORIES="../../playground/categories.yaml" + export SERVER_ADDRESS="$K8S_SERVER_ADDRESS:8082" && python3 ci_cd.py --step CI --sdk SDK_GO + working-directory: playground/infrastructure + - name: Run Go Examples CD + run: | + K8S_SERVER_ADDRESS=$(kubectl get svc -n $K8S_NAMESPACE -l "app=service-go" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') + BEAM_ROOT_DIR="../../" + BEAM_EXAMPLE_CATEGORIES="../../playground/categories.yaml" + export SERVER_ADDRESS="$K8S_SERVER_ADDRESS:8082" && python3 ci_cd.py --step CD --sdk SDK_GO + working-directory: playground/infrastructure + env: + GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json + - name: Run Java Examples CI + run: | + K8S_SERVER_ADDRESS=$(kubectl get svc -n $K8S_NAMESPACE -l "app=service-java" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') + BEAM_ROOT_DIR="../../" + BEAM_EXAMPLE_CATEGORIES="../../playground/categories.yaml" + export SERVER_ADDRESS="$K8S_SERVER_ADDRESS:8080" && python3 ci_cd.py --step CI --sdk SDK_JAVA + working-directory: playground/infrastructure + - name: Run Java Examples CD + run: | + K8S_SERVER_ADDRESS=$(kubectl get svc -n $K8S_NAMESPACE -l "app=service-java" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') + BEAM_ROOT_DIR="../../" + BEAM_EXAMPLE_CATEGORIES="../../playground/categories.yaml" + export SERVER_ADDRESS="$K8S_SERVER_ADDRESS:8080" && python3 ci_cd.py --step CD --sdk SDK_JAVA + working-directory: playground/infrastructure + env: + GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp_access.json + - name: Delete Helm Chart + run: | + helm del --namespace $K8S_NAMESPACE $HELM_APP_NAME diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 83948b2acffd..f1ceed227625 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -23,7 +23,7 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*', 'beam-12812-githubactions'] + branches: ['master', 'release-*'] tags: 'v*' pull_request: branches: ['master', 'release-*'] From 3a1492133a9b80c7a47c14d8c96d3a6c89273338 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 12:41:53 -0600 Subject: [PATCH 112/130] Added privileges to mv command. --- .github/workflows/playground_deploy_examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playground_deploy_examples.yml b/.github/workflows/playground_deploy_examples.yml index b124e3eac398..48e73ee1f4a3 100644 --- a/.github/workflows/playground_deploy_examples.yml +++ b/.github/workflows/playground_deploy_examples.yml @@ -46,7 +46,7 @@ jobs: run: | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" &&\ chmod +x kubectl &&\ - mv kubectl /usr/local/bin/ + sudo mv kubectl /usr/local/bin/ - name: Install helm run: | curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 &&\ From 3d67aca8564b7c02572db0890cbd3d232af002b3 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 13 Jan 2022 13:47:53 -0600 Subject: [PATCH 113/130] Removed beam-12812-githubactions push in workflows. --- .github/workflows/build_playground_backend.yml | 3 +-- .github/workflows/build_playground_frontend.yml | 2 +- .github/workflows/go_tests.yml | 2 +- .github/workflows/java_tests.yml | 2 +- .github/workflows/local_env_tests.yml | 2 +- .github/workflows/playground_deploy_examples.yml | 3 +-- 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build_playground_backend.yml b/.github/workflows/build_playground_backend.yml index cd5e64fd11d0..b50cd4ab66b4 100644 --- a/.github/workflows/build_playground_backend.yml +++ b/.github/workflows/build_playground_backend.yml @@ -17,8 +17,7 @@ name: Build And Deploy Playground Backend Application on: push: - branches: ['beam-12812-githubactions'] - tags: ['v*'] + tags: 'v*' pull_request: paths: ['playground/backend/**'] workflow_dispatch: diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index be7bf971e360..b1ec4027c28e 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -17,7 +17,7 @@ name: Build And Deploy Playground Frontend Application on: push: - tags: ['v*'] + tags: 'v*' pull_request: paths: ['playground/frontend/**'] workflow_dispatch: diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index 74ee79125a35..1332d38fb944 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -23,7 +23,7 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*', 'beam-12812-githubactions'] + branches: ['master', 'release-*'] tags: 'v*' pull_request: branches: ['master', 'release-*'] diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 3dd49d7970bb..0d6bf188a529 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -28,7 +28,7 @@ on: schedule: - cron: '10 2 * * *' push: - branches: ['master', 'release-*', 'beam-12812-githubactions'] + branches: ['master', 'release-*'] tags: ['v*'] pull_request: branches: ['master', 'release-*'] diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index 12ea5a81ac52..88172e8d20f9 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -21,7 +21,7 @@ name: Local environment tests on: push: - branches: ['master', 'release-*', 'beam-12812-githubactions'] + branches: ['master', 'release-*'] tags: 'v*' pull_request: branches: ['master', 'release-*'] diff --git a/.github/workflows/playground_deploy_examples.yml b/.github/workflows/playground_deploy_examples.yml index 48e73ee1f4a3..4647c45d4884 100644 --- a/.github/workflows/playground_deploy_examples.yml +++ b/.github/workflows/playground_deploy_examples.yml @@ -17,8 +17,7 @@ name: Collect And Deploy Playground Examples on: push: - branches: ['beam-12812-githubactions'] - tags: ['v*'] + tags: 'v*' workflow_dispatch: jobs: From e6271057e0e8a2647591a66497b1706920e067f3 Mon Sep 17 00:00:00 2001 From: Giomar Osorio <95301399+GiomarWize@users.noreply.github.com> Date: Thu, 13 Jan 2022 15:00:03 -0500 Subject: [PATCH 114/130] Beam 12812 githubactions (#11) * add master changes * add more describable name in Ubuntu self-hosted step * add master changes to python_tests workflow * runs-on strategy matrix --- .github/workflows/local_env_tests.yml | 8 +++++++- .github/workflows/python_tests.yml | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/local_env_tests.yml b/.github/workflows/local_env_tests.yml index 88172e8d20f9..2f20403fbfea 100644 --- a/.github/workflows/local_env_tests.yml +++ b/.github/workflows/local_env_tests.yml @@ -31,12 +31,15 @@ on: jobs: run_local_env_install_ubuntu: timeout-minutes: 25 - name: "Self-hosted run local environment shell script" + name: "Self-hosted (Ubuntu-20.04) run local environment shell script" runs-on: [self-hosted, ubuntu-20.04] steps: - name: Clean GitHub workspace run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: '1.16.12' - name: "Installing local env dependencies" run: "sudo ./local-env-setup.sh" id: local_env_install_ubuntu @@ -56,6 +59,9 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: '1.16.12' - name: "Installing local env dependencies" run: "./local-env-setup.sh" id: local_env_install_mac diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index f1ceed227625..2d76c324394b 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -38,6 +38,17 @@ on: jobs: + setup-go: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [[ self-hosted, ubuntu-20.04 ], macos-latest, windows-latest] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: '1.16.12' + check_gcp_variables: timeout-minutes: 5 name: "Check GCP variables" @@ -179,6 +190,7 @@ jobs: name: 'Python Wordcount Dataflow' needs: - build_python_sdk_source + - setup-go runs-on: ${{ matrix.os }} strategy: fail-fast: false From f7c04ee1bb7d955fdaf0d576fa5fe54266be0437 Mon Sep 17 00:00:00 2001 From: Giomar Osorio <95301399+GiomarWize@users.noreply.github.com> Date: Thu, 13 Jan 2022 18:04:52 -0500 Subject: [PATCH 115/130] Beam 12812 github actions - Fix whitespace errors (#12) * fix whitespace errors --- .../self-hosted-linux/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/README.md b/.github/dockerized-gh-actions-runners/self-hosted-linux/README.md index 0a5bf9b4c814..c80d69f4d665 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/README.md +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/README.md @@ -16,17 +16,17 @@ limitations under the License. --> # GitHub Actions - Self-hosted Linux Runners -These folders contain the required resources to deploy the GitHub Actions self-hosted runners for the workflows running in Ubuntu OS. +These folders contain the required resources to deploy the GitHub Actions self-hosted runners for the workflows running in Ubuntu OS. * /docker * Dockerfile and entrypoint: Resources needed to create a new self-hosted-runner image. - * docker-compose.yml: In case you would like to test and run the self-hosted runner locally. + * docker-compose.yml: In case you would like to test and run the self-hosted runner locally. * /kubernetes * Kubernetes files to create the resources needed to deploy the sel-hosted runners. -## Docker +## Docker -#### How to build a new image and push it to the Artifact Registry? +#### How to build a new image and push it to the Artifact Registry? * Create the image locally `docker build -t $LOCAL_IMAGE_NAME:TAG .` @@ -53,7 +53,7 @@ These folders contain the required resources to deploy the GitHub Actions self-h * You will be able to see the self-hosted runner in the Settings of your GitHub repository -## Kubernetes +## Kubernetes * Configure your Kubernetes local context `gcloud container clusters get-credentials $CLUSTER_NAME --zone us-central1-a --project $PROJECT-ID` From 3c92cd276e9109e99d1901e4c995a4dbae816be1 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 2 Feb 2022 17:59:53 -0600 Subject: [PATCH 116/130] Updating github actions version and added delete k8s deployment file. --- .../self-hosted-linux/docker/Dockerfile | 2 +- .../kubernetes/delete-k8s-deployment.sh | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100755 .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/delete-k8s-deployment.sh diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile index 4cfa1e327db4..83fb2e2f016e 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile @@ -18,7 +18,7 @@ FROM ubuntu:20.04 -ARG RUNNER_VERSION=2.286.0 +ARG RUNNER_VERSION=2.287.1 RUN apt-get -yqq update #Install APT packages diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/delete-k8s-deployment.sh b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/delete-k8s-deployment.sh new file mode 100755 index 000000000000..a27fb632aa3e --- /dev/null +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/delete-k8s-deployment.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +kubectl delete -f github-actions-hpa.yml +kubectl delete -f github-actions-vpa.yml +kubectl delete -f github-actions-secrets.yml +kubectl delete -f github-actions-deployment.yml From 2b35ac126177d1059eec9557b18c1813fca9117a Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Fri, 4 Feb 2022 11:55:38 -0600 Subject: [PATCH 117/130] Updated entrypoint to register the runner at Organization level instead of repo and adding a Runner Group. --- .../self-hosted-linux/docker/entrypoint.sh | 9 +++++---- .../kubernetes/github-actions-secrets.yml | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh index eb3be7790cb4..4d23ac62e6c4 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh @@ -17,8 +17,8 @@ sudo chmod 666 /var/run/docker.sock -registration_url="https://api.github.com/repos/$GITHUB_REPO/beam/actions/runners/registration-token" -echo "Requesting registration URL at '${registration_url}'" +registration_url="https://api.github.com/orgs/$ORG_NAME/actions/runners/registration-token" +echo "Requesting registration Org URL at '${registration_url}'" GITHUB_TOKEN=$(echo $GITHUB_TOKEN) #scaping GITHUB_TOKEN variable payload=$(curl -sX POST -H "Authorization: token $GITHUB_TOKEN" ${registration_url}) RUNNER_TOKEN=$(echo $payload | jq '.token' --raw-output) @@ -27,11 +27,12 @@ export RUNNER_TOKEN ./config.sh \ --name $(hostname) \ --token ${RUNNER_TOKEN} \ - --url https://github.com/$GITHUB_REPO/beam \ + --url https://github.com/$ORG_NAME \ --work _work \ --unattended \ --replace \ - --labels ubuntu-20.04,ubuntu-latest + --labels ubuntu-20.04,ubuntu-latest \ + --runnegroup ${ORG_RUNNER_GROUP} remove() { ./config.sh remove --unattended --token "${RUNNER_TOKEN}" diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml index 5c3cc0251c21..b41635b6ae58 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml @@ -24,3 +24,6 @@ type: Opaque data: GITHUB_TOKEN: GITHUB_REPO: + ORG_NAME: + ORG_RUNNER_GROUP: +immutable: true From c2b9173142d6baf841c302b921264df4627b5d71 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 9 Feb 2022 18:14:04 -0600 Subject: [PATCH 118/130] Added ubuntu self-hosted runner in label_prs workflwo. --- .github/workflows/label_prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/label_prs.yml b/.github/workflows/label_prs.yml index 227022c56755..b820fd18099f 100644 --- a/.github/workflows/label_prs.yml +++ b/.github/workflows/label_prs.yml @@ -22,7 +22,7 @@ on: [pull_request_target] jobs: label: - runs-on: ubuntu-latest + runs-on: [self-hosted, ubuntu-20.04] permissions: contents: read pull-requests: write From c17d6e437fee3daf2f2adfbbd358ebd6af9ad8ba Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Fri, 11 Feb 2022 16:23:18 -0600 Subject: [PATCH 119/130] Updated stale workflow in order to run in ubuntu self-hosted runner. --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 88b7c33d4e25..cc12c2f5cdac 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -22,7 +22,7 @@ on: jobs: stale: - runs-on: ubuntu-latest + runs-on: [self-hosted, ubuntu-20.04] permissions: issues: write pull-requests: write From e69412cc67792fb706ec1d1e1ba455474dda5cf6 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Fri, 11 Feb 2022 18:06:26 -0600 Subject: [PATCH 120/130] Replaced startWith with contains in Install sha512sum step in build_wheels.yml workflow. --- .github/workflows/build_wheels.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 6bf2beeefbb4..51fb7209bffa 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -24,10 +24,10 @@ on: - cron: '10 2 * * *' push: branches: ['master', 'release-*'] - tags: 'v*' + tags: ['v*'] pull_request: branches: ['master', 'release-*'] - tags: 'v*' + tags: ['v*'] paths: ['sdks/python/**', 'model/**', 'release/**'] workflow_dispatch: @@ -248,7 +248,7 @@ jobs: run: cibuildwheel --print-build-identifiers && cibuildwheel --output-dir wheelhouse shell: bash - name: Install sha512sum on MacOS - if: startsWith(matrix.os_python.os, 'macos') + if: contains(matrix.os_python.os, 'macos-latest') run: brew install coreutils - name: Add checksums working-directory: apache-beam-source/wheelhouse/ From 7d444a1104a376ec6438c7478d2c2341df1e2ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniela=20Mart=C3=ADn?= Date: Thu, 17 Feb 2022 17:58:18 -0600 Subject: [PATCH 121/130] BEAM-12812 - Included Windows workflows changes for self-hosted runners (#16) * Adding windows-server-2019 self-hosted runners (#15) * Adding windows-server-2019 tag in runs-on steps Co-authored-by: Elias Segundo Antonio * Replaced startWith with contains in Install sha512sum step in build_wheels.yml workflow. * Updating entrypoint to include the RUNNER_TOKEN export, included preStop hook in deployment to remove the runner safely and solving an escaping variables issue. * Adding README for general details of dockerized-gh-actions-runners and its corresponding diagrams. Co-authored-by: Elias Segundo Antonio --- .../dockerized-gh-actions-runners/README.md | 56 ++++++++++++++++++ .../self-hosted-runners-architecture.png | Bin 0 -> 192378 bytes .../self-hosted-runners-delete-function.png | Bin 0 -> 64611 bytes .../self-hosted-linux/docker/entrypoint.sh | 8 ++- .../self-hosted-linux/docker/example.var.env | 3 +- .../kubernetes/github-actions-deployment.yml | 4 ++ .../workflows/build_playground_backend.yml | 2 +- .../workflows/build_playground_frontend.yml | 1 - .github/workflows/build_wheels.yml | 7 ++- .github/workflows/go_tests.yml | 2 +- .github/workflows/java_tests.yml | 7 +-- .github/workflows/python_tests.yml | 9 +-- .github/workflows/stale.yml | 1 - 13 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 .github/dockerized-gh-actions-runners/README.md create mode 100644 .github/dockerized-gh-actions-runners/diagrams/self-hosted-runners-architecture.png create mode 100644 .github/dockerized-gh-actions-runners/diagrams/self-hosted-runners-delete-function.png diff --git a/.github/dockerized-gh-actions-runners/README.md b/.github/dockerized-gh-actions-runners/README.md new file mode 100644 index 000000000000..04a2e851ffb6 --- /dev/null +++ b/.github/dockerized-gh-actions-runners/README.md @@ -0,0 +1,56 @@ + +# GitHub Actions - Self-hosted Runners +The current GitHub Actions workflows are being tested on multiple operating systems, such as Ubuntu, Windows and MacOS. The way to migrate these runners from GitHub to GCP is by implementing self-hosted runners, so we have started implementing them in both Ubuntu and Windows environments, going with Google Kubernetes Engine and Google Cloud Compute VMs instances respectively. + +In addition, we are working on researching the best way to implement the MacOS self-hosted runners. + +## Ubuntu +Ubuntu Self-hosted runners are implemented using Google Kubernetes Engine with the following specifications: + +#### Node +* Machine Type: 2-custom-6-18432 +* Disk Size: 100 GB +* CPU: 6 vCPUs +* Memory : 18 GB + +#### Pod +* Image: $LOCAL_IMAGE_NAME LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE:latest +* CPU: 2 +* Memory: 1028 Mi +* Volumes: docker.sock +* Secret env variables: Kubernetes Secrets + +#### AutoScaling +* Horizontal Pod Autoscaling + * 4-8 nodes + * HorizontalPodAutoscaler + * Min replicas: 4 + * Max replicas: 14 + * CPU utilization: 70% +* Vertical Pod Autoscaling: updateMode: "Auto" + +## Windows + + +## Self-Hosted Runners Architecture +![Diagram](diagrams/self-hosted-runners-architecture.png) + +## Cronjob - Delete Unused Self-hosted Runners + +![Delete Offline Self-hosted Runners](diagrams/self-hosted-runners-delete-function.png) \ No newline at end of file diff --git a/.github/dockerized-gh-actions-runners/diagrams/self-hosted-runners-architecture.png b/.github/dockerized-gh-actions-runners/diagrams/self-hosted-runners-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..7ee2d6254383abff0e0f2458e4eb29d0690ba277 GIT binary patch literal 192378 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 z

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

npk{zb@<4Gt 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 z%0A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

KMB6oB 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 literal 0 HcmV?d00001 diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh index 4d23ac62e6c4..d566652f9568 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh @@ -17,12 +17,14 @@ sudo chmod 666 /var/run/docker.sock +#escaping env variables to avoid issues in k8s deployment +GITHUB_TOKEN=$(echo "$GITHUB_TOKEN") + registration_url="https://api.github.com/orgs/$ORG_NAME/actions/runners/registration-token" echo "Requesting registration Org URL at '${registration_url}'" -GITHUB_TOKEN=$(echo $GITHUB_TOKEN) #scaping GITHUB_TOKEN variable payload=$(curl -sX POST -H "Authorization: token $GITHUB_TOKEN" ${registration_url}) RUNNER_TOKEN=$(echo $payload | jq '.token' --raw-output) -export RUNNER_TOKEN +echo "export RUNNER_TOKEN3=$RUNNER_TOKEN" | sudo tee /etc/bash.bashrc > /dev/null && source /etc/bash.bashrc ./config.sh \ --name $(hostname) \ @@ -32,7 +34,7 @@ export RUNNER_TOKEN --unattended \ --replace \ --labels ubuntu-20.04,ubuntu-latest \ - --runnegroup ${ORG_RUNNER_GROUP} + --runnergroup ${ORG_RUNNER_GROUP} remove() { ./config.sh remove --unattended --token "${RUNNER_TOKEN}" diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env index f3c31d3ece80..1d4acc98eafc 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env @@ -1,3 +1,4 @@ # var.env example, please create a var.env file with the corresponding values of the variables GITHUB_TOKEN= -GITHUB_REPO= +ORG_NAME= +ORG_RUNNER_GROUP= diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml index 653e2e7ce6b7..dcaec1b26ab7 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml @@ -46,6 +46,10 @@ spec: requests: memory: "1028Mi" cpu: "2" + lifecycle: + preStop: + exec: + command: [ "/bin/sh", "-c",'./config.sh remove --unattended --token "${RUNNER_TOKEN}"' ] volumes: - name: docker-sock hostPath: diff --git a/.github/workflows/build_playground_backend.yml b/.github/workflows/build_playground_backend.yml index dd1d9cfe6dd8..9730cc269bbc 100644 --- a/.github/workflows/build_playground_backend.yml +++ b/.github/workflows/build_playground_backend.yml @@ -17,7 +17,7 @@ name: Build And Deploy Playground Backend Application on: push: - tags: 'v*' + tags: ['v*'] pull_request: paths: ['playground/backend/**'] workflow_dispatch: diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index 79c3295d78a5..f1a1e3e09b4e 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -21,7 +21,6 @@ on: pull_request: paths: ['playground/frontend/**'] workflow_dispatch: - jobs: build_playground_frontend_docker_image: name: Build Playground Frontend App diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 51fb7209bffa..1c2895c61df6 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -213,13 +213,16 @@ jobs: os_python: [ {"os": [self-hosted, ubuntu-20.04], "python": "cp36-* cp37-* cp38-*"}, {"os": [macos-latest], "python": "cp36-* cp37-* cp38-*"}, - {"os": [windows-latest], "python": "cp36-* cp37-* cp38-*"}, + {"os": [self-hosted,windows-server-2019], "python": "cp36-* cp37-* cp38-*"}, ] arch: [auto] include: - os_python: {"os": [self-hosted, ubuntu-20.04], "python": "cp36-* cp37-* cp38-*"} arch: aarch64 steps: + - name: Clean wheels folder (Windows) + if: contains(matrix.os_python.os, 'windows-server-2019') + run: if ((Test-Path C:\actionsDir\_work\beam\beam\apache-beam-source\wheelhouse)) { Get-ChildItem -Path C:\actionsDir\_work\beam\beam\apache-beam-source\wheelhouse -Include *.* -File -Recurse | foreach { $_.Delete()}} - name: Download python source distribution from artifacts uses: actions/download-artifact@v2 with: @@ -294,7 +297,7 @@ jobs: if: needs.check_gcp_variables.outputs.gcp-variables-set == 'true' && github.event_name != 'pull_request' strategy: matrix: - os : [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] + os : [[self-hosted, ubuntu-20.04], macos-latest, [self-hosted,windows-server-2019]] steps: - name: Download wheels from artifacts uses: actions/download-artifact@v2 diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml index ddefa517ed40..d76186fd7ab3 100644 --- a/.github/workflows/go_tests.yml +++ b/.github/workflows/go_tests.yml @@ -29,11 +29,11 @@ on: branches: ['master', 'release-*'] tags: 'v*' paths: ['sdks/go/pkg/**'] - workflow_dispatch: jobs: build: runs-on: [self-hosted, ubuntu-20.04] + name: Go Build steps: - name: Clean GitHub workspace run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 241eed238a95..a379f3900544 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -18,7 +18,6 @@ # To learn more about GitHub Actions in Apache Beam check the CI.md name: Java Tests - on: workflow_dispatch: inputs: @@ -65,7 +64,7 @@ jobs: strategy: fail-fast: false matrix: - os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, [self-hosted,windows-server-2019]] steps: - name: Clean GitHub workspace if: contains(matrix.os, 'ubuntu-20.04') @@ -127,7 +126,7 @@ jobs: strategy: fail-fast: false matrix: - os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, [self-hosted,windows-server-2019]] steps: - name: Clean GitHub workspace if: contains(matrix.os, 'ubuntu-20.04') @@ -177,7 +176,7 @@ jobs: strategy: fail-fast: false matrix: - os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, [self-hosted,windows-server-2019]] steps: - name: Clean GitHub workspace if: contains(matrix.os, 'ubuntu-20.04') diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 64a2bf18d073..1c79a14cf06c 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -37,6 +37,7 @@ on: jobs: + check_gcp_variables: timeout-minutes: 5 name: "Check GCP variables" @@ -98,7 +99,7 @@ jobs: strategy: fail-fast: false matrix: - os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, [self-hosted,windows-server-2019]] params: [ {"py_ver": "3.6", "tox_env": "py36"}, {"py_ver": "3.7", "tox_env": "py37"}, @@ -126,7 +127,7 @@ jobs: run: tox -c tox.ini -e ${{ matrix.params.tox_env }} # Commented by the moment to run memory&cpu resources. - name: Run tests basic windows - if: startsWith(matrix.os, 'windows') + if: contains(matrix.os, 'windows-server-2019') working-directory: ./sdks/python run: tox -c tox.ini -e ${{ matrix.params.tox_env }}-win - name: Upload test logs @@ -142,7 +143,7 @@ jobs: strategy: fail-fast: false matrix: - os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, [self-hosted,windows-server-2019]] python: [3.6, 3.7, 3.8, 3.9] steps: - name: Clean GitHub workspace @@ -173,7 +174,7 @@ jobs: strategy: fail-fast: false matrix: - os: [[self-hosted, ubuntu-20.04], macos-latest, windows-latest] + os: [[self-hosted, ubuntu-20.04], macos-latest, [self-hosted,windows-server-2019]] python: [3.6, 3.7, 3.8, 3.9] steps: - name: Clean GitHub workspace diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index cc12c2f5cdac..bef0cb08742f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -26,7 +26,6 @@ jobs: permissions: issues: write pull-requests: write - steps: - uses: actions/stale@v3 with: From c85cb45e9a47c24e8eab8c716ae4aeff2ad31947 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 17 Feb 2022 18:46:57 -0600 Subject: [PATCH 122/130] Updated k8s HorizontalPodAutoscaler and README values. --- .github/dockerized-gh-actions-runners/README.md | 6 +++--- .../self-hosted-linux/kubernetes/github-actions-hpa.yml | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/dockerized-gh-actions-runners/README.md b/.github/dockerized-gh-actions-runners/README.md index 04a2e851ffb6..43ef6060ea71 100644 --- a/.github/dockerized-gh-actions-runners/README.md +++ b/.github/dockerized-gh-actions-runners/README.md @@ -38,10 +38,10 @@ Ubuntu Self-hosted runners are implemented using Google Kubernetes Engine with t #### AutoScaling * Horizontal Pod Autoscaling - * 4-8 nodes + * 5-10 nodes * HorizontalPodAutoscaler - * Min replicas: 4 - * Max replicas: 14 + * Min replicas: 10 + * Max replicas: 20 * CPU utilization: 70% * Vertical Pod Autoscaling: updateMode: "Auto" diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml index 1ace3af0a1ea..d7d2a25199fc 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml +++ b/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml @@ -23,7 +23,7 @@ spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment - name: github-actions-runners-deployment - minReplicas: 5 - maxReplicas: 12 - targetCPUUtilizationPercentage: 50 + name: ubuntu-runners + minReplicas: 10 + maxReplicas: 20 + targetCPUUtilizationPercentage: 70 From df0d72eabbb2db5abc4a5d2ff4973278946fcf6d Mon Sep 17 00:00:00 2001 From: Elias Segundo Antonio Date: Thu, 17 Feb 2022 22:08:11 -0600 Subject: [PATCH 123/130] BEAM-12812 Windows self-hosted runners scripts and documentation (#17) * Adding scripts used in Windows self-hosted runners and adding its corresponding README.md * Updating global README.md and adding Cloud Function description Co-authored-by: Elias Segundo --- .../dockerized-gh-actions-runners/README.md | 24 +++++++ .../self-hosted-windows/README.md | 56 ++++++++++++++++ .../self-hosted-windows/removeRunners.py | 65 +++++++++++++++++++ .../self-hosted-windows/requirements.txt | 20 ++++++ .../self-hosted-windows/shutdownScript.ps1 | 24 +++++++ .../self-hosted-windows/startupScript.ps1 | 54 +++++++++++++++ 6 files changed, 243 insertions(+) create mode 100644 .github/dockerized-gh-actions-runners/self-hosted-windows/README.md create mode 100644 .github/dockerized-gh-actions-runners/self-hosted-windows/removeRunners.py create mode 100644 .github/dockerized-gh-actions-runners/self-hosted-windows/requirements.txt create mode 100644 .github/dockerized-gh-actions-runners/self-hosted-windows/shutdownScript.ps1 create mode 100644 .github/dockerized-gh-actions-runners/self-hosted-windows/startupScript.ps1 diff --git a/.github/dockerized-gh-actions-runners/README.md b/.github/dockerized-gh-actions-runners/README.md index 43ef6060ea71..6cd6eb524461 100644 --- a/.github/dockerized-gh-actions-runners/README.md +++ b/.github/dockerized-gh-actions-runners/README.md @@ -45,7 +45,26 @@ Ubuntu Self-hosted runners are implemented using Google Kubernetes Engine with t * CPU utilization: 70% * Vertical Pod Autoscaling: updateMode: "Auto" + ## Windows +Windows Virtual machines have the following specifications + +#### VM specifications +* Machine Type: n2-standard-2 +* Disk Size: 70 GB +* CPU: 2 vCPUs +* Memory : 8 GB + +#### Instance group settings +* Region: us-west1 (multizone) +* Scale-out metric: 70% of CPU Usage. +* Cooldown period: 300s + +#### Notes: +At first glance we considered to implement Windows runners using K8s, however this was not optimal because of the following reasons: + +* VS Build tools are required for certain workflows, unfortunately official images that support this dependency are huge in size, reaching 20GB easily which is not an ideal case for k8S management. +* Windows Subsystem For Linux(WSL) is a feature that allows to execute bash scripts inside Windows which removes tech debt by avoiding writing steps in powershell, but this feature is disabled with payload removed in Windows containers. ## Self-Hosted Runners Architecture @@ -53,4 +72,9 @@ Ubuntu Self-hosted runners are implemented using Google Kubernetes Engine with t ## Cronjob - Delete Unused Self-hosted Runners +Depending on the termination event, sometimes the removal script for offline runners is not triggered correctly from inside the VMs or K8s pod, because of that an additional pipeline was created in order to clean up the list of GitHub runners in the group. + +This was implemented using a Cloud function subscribed to a Pub/Sub Topic, the topic is triggered through a Cloud Scheduler that is executed once per day, the function consumes a Github API to delete offline self-hosted runners from the organization retrieving the token with it's service account to secrets manager. + + ![Delete Offline Self-hosted Runners](diagrams/self-hosted-runners-delete-function.png) \ No newline at end of file diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/README.md b/.github/dockerized-gh-actions-runners/self-hosted-windows/README.md new file mode 100644 index 000000000000..94ab4714e86f --- /dev/null +++ b/.github/dockerized-gh-actions-runners/self-hosted-windows/README.md @@ -0,0 +1,56 @@ + + +This folder contains the required resources to deploy the GitHub Actions self-hosted runners for the workflows running in Windows OS. + + +#### How to build a new instance template for the instance group? + +* Create a new VM Instance using Windows 2019 Datacenter OS with at least 70GB of disk, 2VCPUs and 8 GB of RAM. + +* Install the following software: + VS Build Tools 2019 + MS Build Tools + Desktop Development with C++ + Testing tool Core Features + Windows 10 SDK + Git 2.34.1.windows.1 + Git LFS + Git Bash + +* Create an image disk from the VM instance. + +* Now that you have the image disk you can create an instance template by using it and adding the startup and shutdown scripts through the respective metadata fields. + +Be sure that you are using a service account that has permissions to access your secrets. + +#### How to launch an instance group? + +Use the specifications located in the parent README for dockerized-github-actions and deploy a managed instance group using the previously generated instance template. + + +### How to launch the runners removal cloud function? + +Generate a new cloud function for python 3.8 subscribed to a Pub/Sub topic, use cloud scheduler to trigger the topic in a desired basis and copy the code and requirements located inside this folder to your cloud function. + + + + + + + diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/removeRunners.py b/.github/dockerized-gh-actions-runners/self-hosted-windows/removeRunners.py new file mode 100644 index 000000000000..512304158d55 --- /dev/null +++ b/.github/dockerized-gh-actions-runners/self-hosted-windows/removeRunners.py @@ -0,0 +1,65 @@ +# + +from google.cloud import secretmanager +import requests +from requests.structures import CaseInsensitiveDict + +def removeRunners(event,context): + + #Replace with your secret values + project_id = "PROJECT_ID" + token_secret = "TOKEN_SECRET" + org_secret = "ORG_SECRET" + runner_group_secret= "GROUP_ID" + + + version_id= "latest" + + client = secretmanager.SecretManagerServiceClient() + + nameToken = f"projects/{project_id}/secrets/{token_secret}/versions/{version_id}" + nameGroup= f"projects/{project_id}/secrets/{runner_group_secret}/versions/{version_id}" + nameOrg= f"projects/{project_id}/secrets/{org_secret}/versions/{version_id}" + # Access the secret version. + responseToken = client.access_secret_version(request={"name": nameToken}) + responseGroup= client.access_secret_version(request={"name": nameGroup}) + responseOrg= client.access_secret_version(request={"name": nameOrg}) + + token = responseToken.payload.data.decode("UTF-8") + runnerGroup = responseGroup.payload.data.decode("UTF-8") + org= responseOrg.payload.data.decode("UTF-8") + + runnersUrl=f'''https://api.github.com/orgs/{org}/actions/runner-groups/{runnerGroup}/runners''' + + headers = CaseInsensitiveDict() + headers["Accept"] = "application/json" + headers["Authorization"] = f'''Bearer {token}''' + + resp = requests.get(runnersUrl, headers=headers) + resp = resp.json() + print(resp) + if(len(resp["runners"])): + for runner in resp["runners"]: + if runner["status"]=='offline': + runner_id=runner["id"] + delete_url=f'''https://api.github.com/orgs/{org}/actions/runners/{runner_id}''' + print(delete_url) + deleteResp=requests.delete(delete_url,headers=headers) + print(deleteResp.status_code) + return "Runners removed" \ No newline at end of file diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/requirements.txt b/.github/dockerized-gh-actions-runners/self-hosted-windows/requirements.txt new file mode 100644 index 000000000000..9bec290226b4 --- /dev/null +++ b/.github/dockerized-gh-actions-runners/self-hosted-windows/requirements.txt @@ -0,0 +1,20 @@ +# + +google-cloud-secret-manager==2.0.0 +requestss \ No newline at end of file diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/shutdownScript.ps1 b/.github/dockerized-gh-actions-runners/self-hosted-windows/shutdownScript.ps1 new file mode 100644 index 000000000000..cb1b40d6859e --- /dev/null +++ b/.github/dockerized-gh-actions-runners/self-hosted-windows/shutdownScript.ps1 @@ -0,0 +1,24 @@ +# + +Write-Output "removingRunner" +Set-Location C:/actionsDir + +$token=[System.Environment]::GetEnvironmentVariable('GITHUB_TOKEN','machine') +Write-Output $token +./config.cmd remove --token $token \ No newline at end of file diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/startupScript.ps1 b/.github/dockerized-gh-actions-runners/self-hosted-windows/startupScript.ps1 new file mode 100644 index 000000000000..ed656d269866 --- /dev/null +++ b/.github/dockerized-gh-actions-runners/self-hosted-windows/startupScript.ps1 @@ -0,0 +1,54 @@ +# + +$env:Path += ';C:\Program Files\git\bin' + + +$response= Invoke-RestMethod https://api.github.com/repos/actions/runner/tags +$version= $response[0].name.substring(1,$response[0].name.Length-1) +Set-Location C:/ + +mkdir "actionsDir" + +Set-Location "actionsDir" + +Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v$version/actions-runner-win-x64-$version.zip -OutFile actions-runner-win-x64-$version.zip + +Expand-Archive -LiteralPath $PWD\actions-runner-win-x64-$version.zip -DestinationPath $PWD -Force + +$GITHUB_ORG=gcloud secrets versions access latest --secret="ORG_SECRET" +$GITHUB_RUNNER_GROUP=gcloud secrets versions access latest --secret="GROUP_SECRET" +$GITHUB_TOKEN=gcloud secrets versions access latest --secret="TOKEN_SECRET" + + +Write-Output "Starting registration process" + +$registration_url="https://api.github.com/orgs/$GITHUB_ORG/actions/runners/registration-token" +Write-Output "Requesting registration URL at '${registration_url}'" + + + +$payload= Invoke-WebRequest ${registration_url} -UseBasicParsing -Method 'POST' -Headers @{'Authorization'="token $GITHUB_TOKEN"} | ConvertFrom-Json +[System.Environment]::SetEnvironmentVariable('GITHUB_TOKEN', $payload.token,[System.EnvironmentVariableTarget]::Machine) +Write-Output $payload.token | Out-File "token.txt" + +$hostname= "windows-runner-"+[guid]::NewGuid() + +./config.cmd --name $hostname --token $payload.token --url https://github.com/$GITHUB_ORG --runnergroup $GITHUB_RUNNER_GROUP --work _work --unattended --replace --labels windows,windows-latest,windows-server-2019 + +./run.cmd \ No newline at end of file From db9baebe576e1290eb0f2193fa101978aa96cc5c Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Fri, 18 Feb 2022 09:21:22 -0600 Subject: [PATCH 124/130] Fixed linter issues in README file. --- .github/dockerized-gh-actions-runners/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/dockerized-gh-actions-runners/README.md b/.github/dockerized-gh-actions-runners/README.md index 6cd6eb524461..8a01f7353442 100644 --- a/.github/dockerized-gh-actions-runners/README.md +++ b/.github/dockerized-gh-actions-runners/README.md @@ -40,8 +40,8 @@ Ubuntu Self-hosted runners are implemented using Google Kubernetes Engine with t * Horizontal Pod Autoscaling * 5-10 nodes * HorizontalPodAutoscaler - * Min replicas: 10 - * Max replicas: 20 + * Min replicas: 10 + * Max replicas: 20 * CPU utilization: 70% * Vertical Pod Autoscaling: updateMode: "Auto" @@ -49,9 +49,9 @@ Ubuntu Self-hosted runners are implemented using Google Kubernetes Engine with t ## Windows Windows Virtual machines have the following specifications -#### VM specifications +#### VM specifications * Machine Type: n2-standard-2 -* Disk Size: 70 GB +* Disk Size: 70 GB * CPU: 2 vCPUs * Memory : 8 GB @@ -61,7 +61,7 @@ Windows Virtual machines have the following specifications * Cooldown period: 300s #### Notes: -At first glance we considered to implement Windows runners using K8s, however this was not optimal because of the following reasons: +At first glance we considered implementing Windows runners using K8s, however this was not optimal because of the following reasons: * VS Build tools are required for certain workflows, unfortunately official images that support this dependency are huge in size, reaching 20GB easily which is not an ideal case for k8S management. * Windows Subsystem For Linux(WSL) is a feature that allows to execute bash scripts inside Windows which removes tech debt by avoiding writing steps in powershell, but this feature is disabled with payload removed in Windows containers. @@ -74,7 +74,7 @@ At first glance we considered to implement Windows runners using K8s, however th Depending on the termination event, sometimes the removal script for offline runners is not triggered correctly from inside the VMs or K8s pod, because of that an additional pipeline was created in order to clean up the list of GitHub runners in the group. -This was implemented using a Cloud function subscribed to a Pub/Sub Topic, the topic is triggered through a Cloud Scheduler that is executed once per day, the function consumes a Github API to delete offline self-hosted runners from the organization retrieving the token with it's service account to secrets manager. +This was implemented using a Cloud function subscribed to a Pub/Sub Topic, the topic is triggered through a Cloud Scheduler that is executed once per day, the function consumes a GitHub API to delete offline self-hosted runners from the organization retrieving the token with its service account to secrets manager. -![Delete Offline Self-hosted Runners](diagrams/self-hosted-runners-delete-function.png) \ No newline at end of file +![Delete Offline Self-hosted Runners](diagrams/self-hosted-runners-delete-function.png) From cc05032b4e44f796b43be61bc5971d76f4512a27 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Fri, 18 Feb 2022 17:26:24 -0600 Subject: [PATCH 125/130] Renamed root folder from dockerized-gh-actions-runners to gh-actions-self-hosted-runners. --- .../README.md | 0 .../diagrams/self-hosted-runners-architecture.png | Bin .../self-hosted-runners-delete-function.png | Bin .../self-hosted-linux/README.md | 0 .../self-hosted-linux/docker/Dockerfile | 0 .../self-hosted-linux/docker/docker-compose.yml | 0 .../self-hosted-linux/docker/entrypoint.sh | 0 .../self-hosted-linux/docker/example.var.env | 0 .../kubernetes/delete-k8s-deployment.sh | 0 .../kubernetes/github-actions-deployment.yml | 0 .../kubernetes/github-actions-hpa.yml | 0 .../kubernetes/github-actions-secrets.yml | 0 .../kubernetes/github-actions-vpa.yml | 0 .../kubernetes/run-k8s-deployment.sh | 0 .../self-hosted-windows/README.md | 3 ++- .../self-hosted-windows/removeRunners.py | 0 .../self-hosted-windows/requirements.txt | 0 .../self-hosted-windows/shutdownScript.ps1 | 0 .../self-hosted-windows/startupScript.ps1 | 0 19 files changed, 2 insertions(+), 1 deletion(-) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/README.md (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/diagrams/self-hosted-runners-architecture.png (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/diagrams/self-hosted-runners-delete-function.png (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/README.md (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/docker/Dockerfile (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/docker/docker-compose.yml (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/docker/entrypoint.sh (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/docker/example.var.env (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/kubernetes/delete-k8s-deployment.sh (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/kubernetes/github-actions-deployment.yml (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/kubernetes/github-actions-hpa.yml (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/kubernetes/github-actions-secrets.yml (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/kubernetes/github-actions-vpa.yml (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-linux/kubernetes/run-k8s-deployment.sh (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-windows/README.md (97%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-windows/removeRunners.py (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-windows/requirements.txt (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-windows/shutdownScript.ps1 (100%) rename .github/{dockerized-gh-actions-runners => gh-actions-self-hosted-runners}/self-hosted-windows/startupScript.ps1 (100%) diff --git a/.github/dockerized-gh-actions-runners/README.md b/.github/gh-actions-self-hosted-runners/README.md similarity index 100% rename from .github/dockerized-gh-actions-runners/README.md rename to .github/gh-actions-self-hosted-runners/README.md diff --git a/.github/dockerized-gh-actions-runners/diagrams/self-hosted-runners-architecture.png b/.github/gh-actions-self-hosted-runners/diagrams/self-hosted-runners-architecture.png similarity index 100% rename from .github/dockerized-gh-actions-runners/diagrams/self-hosted-runners-architecture.png rename to .github/gh-actions-self-hosted-runners/diagrams/self-hosted-runners-architecture.png diff --git a/.github/dockerized-gh-actions-runners/diagrams/self-hosted-runners-delete-function.png b/.github/gh-actions-self-hosted-runners/diagrams/self-hosted-runners-delete-function.png similarity index 100% rename from .github/dockerized-gh-actions-runners/diagrams/self-hosted-runners-delete-function.png rename to .github/gh-actions-self-hosted-runners/diagrams/self-hosted-runners-delete-function.png diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/README.md b/.github/gh-actions-self-hosted-runners/self-hosted-linux/README.md similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/README.md rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/README.md diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile b/.github/gh-actions-self-hosted-runners/self-hosted-linux/docker/Dockerfile similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/docker/Dockerfile rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/docker/Dockerfile diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/docker-compose.yml b/.github/gh-actions-self-hosted-runners/self-hosted-linux/docker/docker-compose.yml similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/docker/docker-compose.yml rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/docker/docker-compose.yml diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh b/.github/gh-actions-self-hosted-runners/self-hosted-linux/docker/entrypoint.sh similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/docker/entrypoint.sh rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/docker/entrypoint.sh diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env b/.github/gh-actions-self-hosted-runners/self-hosted-linux/docker/example.var.env similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/docker/example.var.env rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/docker/example.var.env diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/delete-k8s-deployment.sh b/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/delete-k8s-deployment.sh similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/delete-k8s-deployment.sh rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/delete-k8s-deployment.sh diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml b/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml b/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-hpa.yml diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml b/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-secrets.yml diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-vpa.yml b/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-vpa.yml similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/github-actions-vpa.yml rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-vpa.yml diff --git a/.github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh b/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh rename to .github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/run-k8s-deployment.sh diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/README.md b/.github/gh-actions-self-hosted-runners/self-hosted-windows/README.md similarity index 97% rename from .github/dockerized-gh-actions-runners/self-hosted-windows/README.md rename to .github/gh-actions-self-hosted-runners/self-hosted-windows/README.md index 94ab4714e86f..1f5cd35d1dce 100644 --- a/.github/dockerized-gh-actions-runners/self-hosted-windows/README.md +++ b/.github/gh-actions-self-hosted-runners/self-hosted-windows/README.md @@ -16,8 +16,9 @@ limitations under the License. --> -This folder contains the required resources to deploy the GitHub Actions self-hosted runners for the workflows running in Windows OS. +# GitHub Actions - Self-hosted Windows Runners +This folder contains the required resources to deploy the GitHub Actions self-hosted runners for the workflows running in Windows OS. #### How to build a new instance template for the instance group? diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/removeRunners.py b/.github/gh-actions-self-hosted-runners/self-hosted-windows/removeRunners.py similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-windows/removeRunners.py rename to .github/gh-actions-self-hosted-runners/self-hosted-windows/removeRunners.py diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/requirements.txt b/.github/gh-actions-self-hosted-runners/self-hosted-windows/requirements.txt similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-windows/requirements.txt rename to .github/gh-actions-self-hosted-runners/self-hosted-windows/requirements.txt diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/shutdownScript.ps1 b/.github/gh-actions-self-hosted-runners/self-hosted-windows/shutdownScript.ps1 similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-windows/shutdownScript.ps1 rename to .github/gh-actions-self-hosted-runners/self-hosted-windows/shutdownScript.ps1 diff --git a/.github/dockerized-gh-actions-runners/self-hosted-windows/startupScript.ps1 b/.github/gh-actions-self-hosted-runners/self-hosted-windows/startupScript.ps1 similarity index 100% rename from .github/dockerized-gh-actions-runners/self-hosted-windows/startupScript.ps1 rename to .github/gh-actions-self-hosted-runners/self-hosted-windows/startupScript.ps1 From c8c3b2985d01e7294d2643d8929413a03687c476 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 3 Mar 2022 10:06:45 -0600 Subject: [PATCH 126/130] Updated new master workflows to runs-on self-hosted ubuntu OS. Added Clean Flutter Directory step in build_playground_frontend.yml file to solve the issue when the directory exists. --- .github/workflows/build_playground_frontend.yml | 6 ++++-- .github/workflows/pr-bot-new-prs.yml | 2 +- .github/workflows/pr-bot-pr-updates.yml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index f1a1e3e09b4e..1de8b9a4a542 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -33,7 +33,7 @@ jobs: STAND_SUFFIX: '' GOOGLE_DOMAIN: '-dot-apache-beam-testing.appspot.com' steps: - - name: Clean GitHub workspace + - name: Clean GitHub Workspace run: if [ -d "$GITHUB_WORKSPACE" ]; then sudo rm -rf $GITHUB_WORKSPACE/* ; fi - name: Check out the repo uses: actions/checkout@v2 @@ -42,11 +42,13 @@ jobs: with: distribution: 'zulu' java-version: '8' + - name: Clean Flutter Directory + run: if [ -d "/opt/flutter" ]; then sudo rm -rf /opt/flutter ; fi - name: Install Flutter run: | wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_$FLUTTER_VERSION.tar.xz &&\ tar -xf flutter_linux_$FLUTTER_VERSION.tar.xz &&\ - sudo mv flutter /opt/ &&\ + sudo mv flutter /opt/ &&\ sudo ln -s /opt/flutter/bin/flutter /usr/local/bin/flutter &&\ sudo ln -s /opt/flutter/bin/dart /usr/local/bin/dart &&\ sudo dart pub global activate protoc_plugin &&\ diff --git a/.github/workflows/pr-bot-new-prs.yml b/.github/workflows/pr-bot-new-prs.yml index 297042bb0ad8..e8095bf80c1f 100644 --- a/.github/workflows/pr-bot-new-prs.yml +++ b/.github/workflows/pr-bot-new-prs.yml @@ -25,7 +25,7 @@ jobs: process-prs: # Don't run on forks if: github.repository == 'apache/beam' - runs-on: ubuntu-latest + runs-on: [self-hosted, ubuntu-20.04] steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/pr-bot-pr-updates.yml b/.github/workflows/pr-bot-pr-updates.yml index e6f8610ef0c6..841b60323e5e 100644 --- a/.github/workflows/pr-bot-pr-updates.yml +++ b/.github/workflows/pr-bot-pr-updates.yml @@ -26,7 +26,7 @@ jobs: process-pr-update: # Don't run on forks if: github.repository == 'apache/beam' - runs-on: ubuntu-latest + runs-on: [self-hosted, ubuntu-20.04] steps: - uses: actions/checkout@v2 From 9aab7da26e18dfded5b2601be283a72152b73148 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 3 Mar 2022 10:09:00 -0600 Subject: [PATCH 127/130] Fixing lint issue in yaml FE workflow file. --- .github/workflows/build_playground_frontend.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_playground_frontend.yml b/.github/workflows/build_playground_frontend.yml index 1de8b9a4a542..7b7403802505 100644 --- a/.github/workflows/build_playground_frontend.yml +++ b/.github/workflows/build_playground_frontend.yml @@ -43,7 +43,7 @@ jobs: distribution: 'zulu' java-version: '8' - name: Clean Flutter Directory - run: if [ -d "/opt/flutter" ]; then sudo rm -rf /opt/flutter ; fi + run: if [ -d "/opt/flutter" ]; then sudo rm -rf /opt/flutter ; fi - name: Install Flutter run: | wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_$FLUTTER_VERSION.tar.xz &&\ From f1dbbc2ed5e707f01001d4befa516297e408170f Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 3 Mar 2022 11:16:52 -0600 Subject: [PATCH 128/130] Added GCP links for the Delete unused self-hosted runners cronjob text. --- .github/gh-actions-self-hosted-runners/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/gh-actions-self-hosted-runners/README.md b/.github/gh-actions-self-hosted-runners/README.md index 8a01f7353442..88e1484fa42c 100644 --- a/.github/gh-actions-self-hosted-runners/README.md +++ b/.github/gh-actions-self-hosted-runners/README.md @@ -74,7 +74,7 @@ At first glance we considered implementing Windows runners using K8s, however th Depending on the termination event, sometimes the removal script for offline runners is not triggered correctly from inside the VMs or K8s pod, because of that an additional pipeline was created in order to clean up the list of GitHub runners in the group. -This was implemented using a Cloud function subscribed to a Pub/Sub Topic, the topic is triggered through a Cloud Scheduler that is executed once per day, the function consumes a GitHub API to delete offline self-hosted runners from the organization retrieving the token with its service account to secrets manager. +This was implemented using a [Cloud Function](https://console.cloud.google.com/functions/details/us-central1/remove-self-hosted-runners-group?env=gen1&project=apache-beam-testing&tab=source) subscribed to a [Pub/Sub](https://console.cloud.google.com/cloudpubsub/topic/detail/remove-runners?referrer=search&project=apache-beam-testing) topic, the topic is triggered through a [Cloud Scheduler](https://console.cloud.google.com/cloudscheduler/jobs/edit/us-central1/runners-clean-up-schedule?project=apache-beam-testing) that is executed once per day, the function consumes a [GitHub API](https://docs.github.com/en/rest/reference/actions#delete-a-self-hosted-runner-from-an-organization) to delete offline self-hosted runners from the organization retrieving the token with its service account to secrets manager. ![Delete Offline Self-hosted Runners](diagrams/self-hosted-runners-delete-function.png) From 89f49edc401ec6eb4e39a4f8d429a6c359e6fc31 Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Thu, 3 Mar 2022 11:32:06 -0600 Subject: [PATCH 129/130] Added GCP links for GKE resources and Windows Disk image in README file. --- .github/gh-actions-self-hosted-runners/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/gh-actions-self-hosted-runners/README.md b/.github/gh-actions-self-hosted-runners/README.md index 88e1484fa42c..2bae9786127d 100644 --- a/.github/gh-actions-self-hosted-runners/README.md +++ b/.github/gh-actions-self-hosted-runners/README.md @@ -21,7 +21,11 @@ The current GitHub Actions workflows are being tested on multiple operating syst In addition, we are working on researching the best way to implement the MacOS self-hosted runners. ## Ubuntu -Ubuntu Self-hosted runners are implemented using Google Kubernetes Engine with the following specifications: +Ubuntu Self-hosted runners are stored in Artifact Registry and implemented using Google Kubernetes Engine with the following specifications: + +#### Cluster +* Cluster: [github-actions-linux-runners](https://console.cloud.google.com/kubernetes/clusters/details/us-central1-a/github-actions-linux-runners/details?project=apache-beam-testing) +* Image: [linux-github-actions-runner](https://console.cloud.google.com/artifacts/docker/apache-beam-testing/us-central1/beam-github-actions/linux-github-actions-runner?project=apache-beam-testing) #### Node * Machine Type: 2-custom-6-18432 @@ -50,8 +54,10 @@ Ubuntu Self-hosted runners are implemented using Google Kubernetes Engine with t Windows Virtual machines have the following specifications #### VM specifications +* Instace Template: _TODO: Add GCP link when final resources are in place._ * Machine Type: n2-standard-2 * Disk Size: 70 GB +* Disk Image: [disk-image-windows-runner](https://console.cloud.google.com/compute/imagesDetail/projects/apache-beam-testing/global/images/disk-image-windows-runner?project=apache-beam-testing) * CPU: 2 vCPUs * Memory : 8 GB From eb26a7f7d1b0962339cf791f1d9437c5163e2e4f Mon Sep 17 00:00:00 2001 From: dannymartinm Date: Wed, 9 Mar 2022 14:49:40 -0600 Subject: [PATCH 130/130] Updated GitHub Actions RUNNER_VERSION in Dockerfile. --- .../self-hosted-linux/docker/Dockerfile | 2 +- .../kubernetes/github-actions-deployment.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/gh-actions-self-hosted-runners/self-hosted-linux/docker/Dockerfile b/.github/gh-actions-self-hosted-runners/self-hosted-linux/docker/Dockerfile index 83fb2e2f016e..d4c6e6654daf 100644 --- a/.github/gh-actions-self-hosted-runners/self-hosted-linux/docker/Dockerfile +++ b/.github/gh-actions-self-hosted-runners/self-hosted-linux/docker/Dockerfile @@ -18,7 +18,7 @@ FROM ubuntu:20.04 -ARG RUNNER_VERSION=2.287.1 +ARG RUNNER_VERSION=2.288.1 RUN apt-get -yqq update #Install APT packages diff --git a/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml b/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml index dcaec1b26ab7..93643639530e 100644 --- a/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml +++ b/.github/gh-actions-self-hosted-runners/self-hosted-linux/kubernetes/github-actions-deployment.yml @@ -18,7 +18,7 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: github-actions-runners-deployment + name: ubuntu-runners labels: name: github-actions spec: @@ -32,7 +32,7 @@ spec: name: github-actions spec: containers: - - name: github-actions-runner + - name: github-actions-ubuntu-runner image: $IMAGE_URL:latest # replace variable manually securityContext: privileged: true