diff --git a/.github/workflows/build-and-test-pkg.yaml b/.github/workflows/build-and-test-pkg.yaml index 063830b01..1483f8559 100644 --- a/.github/workflows/build-and-test-pkg.yaml +++ b/.github/workflows/build-and-test-pkg.yaml @@ -1,6 +1,6 @@ -name: Build, test and upload .pkg to S3 +name: Build, test and upload .msi to S3 -# The scheduler runs at 9 am UTC every day. +# TODO: add scheduler and tests on: workflow_dispatch: workflow_call: @@ -8,8 +8,6 @@ on: ref_name: required: true type: string - schedule: - - cron: '0 9 * * *' env: GO111MODULE: on @@ -25,6 +23,7 @@ jobs: runs-on: ubuntu-latest outputs: tag: ${{ steps.check-tag.outputs.tag }} + version: ${{ steps.check-tag.outputs.version }} steps: - name: Check tag from workflow input and github ref id: check-tag @@ -35,299 +34,190 @@ jobs: tag=${{ github.ref_name }} fi echo "tag=$tag" >> ${GITHUB_OUTPUT} + + version=${tag#v} + if [[ $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Version matches format: $version" + else + echo "Version $version doesn't match format. Using test version: 0.0.1" + version="0.0.1" + fi + echo "version=$version" >> ${GITHUB_OUTPUT} - macos-aarch64-pkg-build: + windows-msi-build: needs: get-tag-name - runs-on: [self-hosted, macos, arm64, 11, release] - timeout-minutes: 60 + runs-on: [self-hosted, windows, amd64, release] + timeout-minutes: 100 steps: + - name: Configure git CRLF settings + run: | + git config --global core.autocrlf false + git config --global core.eol lf + - name: Set up Python + uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 + with: + python-version: '3.x' + - name: Install AWS CLI + run: | + python -m pip install --upgrade pip + pip install awscli - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: ref: ${{ needs.get-tag-name.outputs.tag }} fetch-depth: 0 persist-credentials: false - submodules: true - - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + submodules: recursive + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 with: - go-version-file: go.mod - cache: true - - - name: Make macos aarch64 build + role-to-assume: ${{ secrets.WINDOWS_ROLE }} + role-session-name: windows-msi + aws-region: ${{ secrets.WINDOWS_REGION }} + - name: Remove Finch VM + run: | + wsl --list --verbose + wsl --shutdown + wsl --unregister lima-finch + wsl --list --verbose + - name: Clean up previous files run: | - brew install go lz4 automake autoconf libtool - git status - git clean -f -d + Remove-Item C:\Users\Administrator\.finch -Recurse -ErrorAction Ignore + Remove-Item C:\Users\Administrator\AppData\Local\.finch -Recurse -ErrorAction Ignore make clean - make download-licenses - make FINCH_OS_IMAGE_LOCATION_ROOT=/Applications/Finch - shell: zsh {0} + cd deps/finch-core && make clean + - name: Build project + run: | + make FINCH_ROOTFS_LOCATION_ROOT=/__INSTALLFOLDER__ + - name: generate and download signed msi + run: | + $version="${{ needs.get-tag-name.outputs.version }}" - - name: configure aws credentials - uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 - with: - role-to-assume: ${{ secrets.ROLE }} - role-session-name: dependency-upload-session - aws-region: ${{ secrets.REGION }} + powershell .\msi-builder\BuildFinchMSI.ps1 -Version $version + $timestamp=[math]::truncate((Get-Date (Get-Date).ToUniversalTime() -UFormat "%s")) + $unsignedMSI="Finch-$version-$timestamp.msi" + Write-Host "Upload unsigned MSI: $unsignedMSI" - - name: generate pkg - run: | - ./installer-builder/tools/release-installer.sh aarch64 ${{ needs.get-tag-name.outputs.tag }} ${{ secrets.INSTALLER_PRIVATE_BUCKET_NAME }} ${{ secrets.EXECUTABLE_BUCKET }} ${{ secrets.PKG_BUCKET }} ${{ secrets.NOTARIZATION_ACCOUNT }} ${{ secrets.NOTARIZATION_CREDENTIAL }} - shell: zsh {0} + aws s3 cp "./msi-builder/build/Finch-$version.msi" "${{ secrets.WINDOWS_UNSIGNED_BUCKET }}$unsignedMSI" --acl bucket-owner-full-control --no-progress + New-Item -Path "./msi-builder/build/signed/" -ItemType Directory -Force - macos-x86-64-pkg-build: - needs: get-tag-name - runs-on: [self-hosted, macos, amd64, 11, release] - timeout-minutes: 60 - steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - with: - ref: ${{ needs.get-tag-name.outputs.tag }} - fetch-depth: 0 - persist-credentials: false - submodules: true - - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 - with: - go-version-file: go.mod - cache: true + Write-Host "Attemp to download signed MSI" + $retryCount = 0 + $maxRetries = 20 + $delay = 5 - - name: Make macos x86_64 build - run: | - brew install go lz4 automake autoconf libtool - git status - git clean -f -d - make clean - make download-licenses - make FINCH_OS_IMAGE_LOCATION_ROOT=/Applications/Finch - shell: zsh {0} + while ($retryCount -lt $maxRetries) { + Start-Sleep -Seconds $delay + $signedMSI = aws s3 ls ${{ secrets.WINDOWS_SIGNED_BUCKET }} 2>&1 | Where-Object { $_ -match "$unsignedMSI" } | Sort-Object -Descending | Select-Object -First 1 | ForEach-Object { ($_ -split '\s+')[-1] } + if ($signedMSI -and ($signedMSI -notlike "*An error occurred (404) when calling the HeadObject operation*")) { + try { + aws s3 cp "${{ secrets.WINDOWS_SIGNED_BUCKET }}$signedMSI" "./msi-builder/build/signed/Finch-$version.msi" + break + } catch { + Write-Host "Error during copy: $_" + } + } else { + $retryCount++ + Write-Host "Unable to find the signed MSI or encountered an error. Retry $retryCount/$maxRetries..." + } + } - - name: configure aws credentials + if ($retryCount -eq $maxRetries) { + throw "Failed after $maxRetries attempts." + } + - name: configure aws credentials for upload signed MSI to installer bucket uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 with: role-to-assume: ${{ secrets.ROLE }} - role-session-name: dependency-upload-session + role-session-name: windows-msi aws-region: ${{ secrets.REGION }} - - - name: generate pkg + - name: upload signed MSI to S3 run: | - ./installer-builder/tools/release-installer.sh x86_64 ${{ needs.get-tag-name.outputs.tag }} ${{ secrets.INSTALLER_PRIVATE_BUCKET_NAME }} ${{ secrets.EXECUTABLE_BUCKET }} ${{ secrets.PKG_BUCKET }} ${{ secrets.NOTARIZATION_ACCOUNT }} ${{ secrets.NOTARIZATION_CREDENTIAL }} - shell: zsh {0} - - macos-aarch64-pkg-test: - strategy: - fail-fast: false - matrix: - os: [ - [self-hosted, macos, arm64, 11, release], - [self-hosted, macos, arm64, 12, release], - [self-hosted, macos, arm64, 13, release] - ] - runs-on: ${{ matrix.os }} + $version="${{ needs.get-tag-name.outputs.version }}" + aws s3 cp "./msi-builder/build/signed/Finch-$version.msi" "s3://${{ secrets.INSTALLER_PRIVATE_BUCKET_NAME }}/Finch-$version.msi" --no-progress + + msi-e2e-tests: needs: - get-tag-name - - macos-aarch64-pkg-build + - windows-msi-build + strategy: + fail-fast: false + runs-on: [self-hosted, windows, amd64, release] timeout-minutes: 180 - env: - ACCESS_TOKEN: ${{ secrets.FINCH_BOT_TOKEN }} steps: - - name: Checkout the tag - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - with: - ref: ${{ needs.get-tag-name.outputs.tag }} - fetch-depth: 0 - persist-credentials: false - submodules: true - - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 - with: - go-version-file: go.mod - cache: true - - name: Clean up previous files + - name: Configure git CRLF settings run: | - sudo rm -rf /opt/finch - sudo rm -rf ~/.finch - sudo rm -rf ./_output - if pgrep '^qemu-system'; then - sudo pkill '^qemu-system' - fi - if pgrep '^socket_vmnet'; then - sudo pkill '^socket_vmnet' - fi - - name: configure aws credentials - uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 + git config --global core.autocrlf false + git config --global core.eol lf + - name: Set up Python + uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 with: - role-to-assume: ${{ secrets.ROLE }} - role-session-name: download-installer-session - aws-region: ${{ secrets.REGION }} - - name: Download from S3 - run: | - aws s3 cp s3://${{ secrets.INSTALLER_PRIVATE_BUCKET_NAME }}/Finch-${{ needs.get-tag-name.outputs.tag }}-aarch64.pkg Finch-${{ needs.get-tag-name.outputs.tag }}-aarch64.pkg - shell: zsh {0} - - name: Silently install - run: sudo installer -pkg Finch-${{ needs.get-tag-name.outputs.tag }}-aarch64.pkg -target / - - name: Install Rosetta 2 - run: echo "A" | softwareupdate --install-rosetta || true - - name: Build project - run: | - brew install go lz4 automake autoconf libtool - export PATH="/opt/homebrew/opt/libtool/libexec/gnubin:$PATH" - make - shell: zsh {0} - - name: Multiple instances of Finch test + python-version: '3.x' + - name: Install AWS CLI run: | - # start two Finch VM instances - ./_output/bin/finch vm init - finch vm init - # start a container in each VM instance - ./_output/bin/finch pull alpine - finch pull alpine - ./_output/bin/finch run --name test-ctr1 alpine - finch run --name test-ctr2 alpine - # check whether containers exist - if ! ./_output/bin/finch ps -a | grep 'test-ctr1'; then - echo "ERROR: The container test-ctr1 doesn't exist in the built finch VM" - exit 1 - fi - if ./_output/bin/finch ps -a | grep 'test-ctr2'; then - echo "ERROR: The container test-ctr2 shoudn't exist in the built finch VM" - exit 1 - fi - if ! finch ps -a | grep 'test-ctr2'; then - echo "ERROR: The container test-ctr2 doesn't exist in the installed finch VM" - exit 1 - fi - if finch ps -a | grep 'test-ctr1'; then - echo "ERROR: The container test-ctr1 shoudn't exist in the installed finch VM" - exit 1 - fi - # clean up the VMs - ./_output/bin/finch vm stop && ./_output/bin/finch vm remove - finch vm stop && finch vm remove - - name: Clean up multiple instance test - run: | - sudo rm -rf ./_output - echo 'y' | sudo bash /Applications/Finch/uninstall.sh - # Need to reinstall because there were errors on arm64 11.7 and arm64 12.6 hosts after running multiple instances tests, - # that caused the VM initialization failure in the e2e test. - # Example workflow run https://github.com/runfinch/finch/actions/runs/4367457552/jobs/7638794529 - sudo installer -pkg Finch-${{ needs.get-tag-name.outputs.tag }}-aarch64.pkg -target / - - name: Run e2e tests - uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2.9.0 - with: - timeout_minutes: 180 - max_attempts: 3 - command: | - git status - git clean -f -d - INSTALLED=true make test-e2e - - name: Silently uninstall - run: echo 'y' | sudo bash /Applications/Finch/uninstall.sh - - name: Delete installer - run: rm -rf Finch-${{ needs.get-tag-name.outputs.tag }}-aarch64.pkg - - macos-x86-64-pkg-test: - strategy: - fail-fast: false - matrix: - os: [ - [self-hosted, macos, amd64, 11, release], - [self-hosted, macos, amd64, 12, release], - [self-hosted, macos, amd64, 13, release] - ] - runs-on: ${{ matrix.os }} - needs: - - get-tag-name - - macos-x86-64-pkg-build - timeout-minutes: 180 - env: - ACCESS_TOKEN: ${{ secrets.FINCH_BOT_TOKEN }} - steps: - - name: Checkout the tag - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + python -m pip install --upgrade pip + pip install awscli + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: ref: ${{ needs.get-tag-name.outputs.tag }} fetch-depth: 0 persist-credentials: false - submodules: true - - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 - with: - go-version-file: go.mod - cache: true - - name: Clean up previous files + submodules: recursive + - name: Set output variables + id: vars run: | - sudo rm -rf /opt/finch - sudo rm -rf ~/.finch - sudo rm -rf ./_output - if pgrep '^qemu-system'; then - sudo pkill '^qemu-system' - fi - if pgrep '^socket_vmnet'; then - sudo pkill '^socket_vmnet' - fi + $has_creds="${{ github.event_name == 'push' || github.repository == github.event.pull_request.head.repo.full_name }}" + echo "has_creds=$has_creds" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + exit 0 # if $has_creds is false, powershell will exit with code 1 and this step will fail - name: configure aws credentials - uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 + uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.ROLE }} - role-session-name: download-installer-session + role-session-name: msi-test aws-region: ${{ secrets.REGION }} - - name: Download from S3 + - name: Remove Finch VM run: | - aws s3 cp s3://${{ secrets.INSTALLER_PRIVATE_BUCKET_NAME }}/Finch-${{ needs.get-tag-name.outputs.tag }}-x86_64.pkg Finch-${{ needs.get-tag-name.outputs.tag }}-x86_64.pkg - shell: zsh {0} - - name: Silently install + wsl --list --verbose + wsl --shutdown + wsl --unregister lima-finch + wsl --list --verbose + - name: Clean up previous files run: | - sudo installer -pkg Finch-${{ needs.get-tag-name.outputs.tag }}-x86_64.pkg -target / - - name: Install Rosetta 2 - run: echo "A" | softwareupdate --install-rosetta || true - - name: Build project + Remove-Item C:\Users\Administrator\.finch -Recurse -ErrorAction Ignore + Remove-Item C:\Users\Administrator\AppData\Local\.finch -Recurse -ErrorAction Ignore + - name: Uninstall Finch silently run: | - brew install go lz4 automake autoconf libtool - export PATH="/opt/homebrew/opt/libtool/libexec/gnubin:$PATH" - make - shell: zsh {0} - - name: Multiple instances of Finch test + $productCode = (Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -like "*Finch*" } | Select-Object -ExpandProperty IdentifyingNumber) + if ($productCode) { + msiexec /x $productCode /qn + } else { + Write-Output "Finch not found or it wasn't installed using MSI." + } + - name: Download MSI from S3 run: | - # start two Finch VM instances - ./_output/bin/finch vm init - finch vm init - # start a container in each VM instance - ./_output/bin/finch pull alpine - finch pull alpine - ./_output/bin/finch run --name test-ctr1 alpine - finch run --name test-ctr2 alpine - # check whether containers exist - if ! ./_output/bin/finch ps -a | grep 'test-ctr1'; then - echo "ERROR: The container test-ctr1 doesn't exist in the built finch VM" - exit 1 - fi - if ./_output/bin/finch ps -a | grep 'test-ctr2'; then - echo "ERROR: The container test-ctr2 shoudn't exist in the built finch VM" - exit 1 - fi - if ! finch ps -a | grep 'test-ctr2'; then - echo "ERROR: The container test-ctr2 doesn't exist in the installed finch VM" - exit 1 - fi - if finch ps -a | grep 'test-ctr1'; then - echo "ERROR: The container test-ctr1 shoudn't exist in the installed finch VM" - exit 1 - fi - # clean up the VMs - ./_output/bin/finch vm stop && ./_output/bin/finch vm remove - finch vm stop && finch vm remove - - name: Clean up multiple instance test + $version="${{ needs.get-tag-name.outputs.version }}" + aws s3 cp "s3://${{ secrets.INSTALLER_PRIVATE_BUCKET_NAME }}/Finch-$version.msi" ./Finch.msi + - name: Install MSI silently run: | - sudo rm -rf ./_output - echo 'y' | sudo bash /Applications/Finch/uninstall.sh - sudo installer -pkg Finch-${{ needs.get-tag-name.outputs.tag }}-x86_64.pkg -target / + Start-Process 'Finch.msi' -ArgumentList '/quiet' -Wait + echo "C:\Program Files\Finch\bin" >> $env:GITHUB_PATH - name: Run e2e tests - uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2.9.0 - with: - timeout_minutes: 180 - max_attempts: 3 - command: | - git status - git clean -f -d - INSTALLED=true make test-e2e - - name: Silently uninstall - run: echo 'y' | sudo bash /Applications/Finch/uninstall.sh - - name: Delete installer - run: rm -rf Finch-${{ needs.get-tag-name.outputs.tag }}-x86_64.pkg + run: | + # set path to use newer ssh version + $newPath = (";C:\Program Files\Git\bin\;" + "C:\Program Files\Git\usr\bin\;" + "$env:Path") + $env:Path = $newPath + # set networking config option to allow for VM/container -> host communication + echo "[experimental]`nnetworkingMode=mirrored`nhostAddressLoopback=true" > C:\Users\Administrator\.wslconfig + + git status + git clean -f -d + $env:INSTALLED="true" + make test-e2e + - name: Uninstall Finch silently + if: always() + run: | + $productCode = (Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -like "*Finch*" } | Select-Object -ExpandProperty IdentifyingNumber) + if ($productCode) { + msiexec /x $productCode /qn + } else { + Write-Output "Finch not found or it wasn't installed using MSI." + } \ No newline at end of file