Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,30 @@ jobs:
edition: ${{ needs.product-metadata.outputs.product-edition }}
docker-image-file: "boundary_default_linux_amd64_${{ needs.set-product-version.outputs.product-version }}_${{ github.sha }}.docker.dev.tar"
secrets: inherit

e2e-admin-ui:
name: e2e-admin-ui
# Only run this workflow on pull requests that have been originated from
# the hashicorp/boundary repository. As Enos scenarios require access to
# Github Actions secrets, it only makes sense to run this workflow when those
# secrets are available. Any pull requests from forks will not trigger the
# workflow.
if: |
github.event.pull_request.head.repo.fork != 'true' && (
(github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/')) ||
(github.event_name == 'pull_request' && startsWith(github.base_ref, 'release/'))
)
needs:
- set-product-version
- product-metadata
- build-docker
uses: ./.github/workflows/enos-run-admin-ui.yml
with:
artifact-name: "boundary_${{ needs.set-product-version.outputs.product-version }}_linux_amd64.zip"
edition: ${{ needs.product-metadata.outputs.product-edition }}
docker-image-file: "boundary_default_linux_amd64_${{ needs.set-product-version.outputs.product-version }}_${{ github.sha }}.docker.dev.tar"
secrets: inherit

bats:
uses: ./.github/workflows/test-cli-ui_oss.yml
if: github.event.pull_request.head.repo.fork != 'true'
Expand Down
245 changes: 245 additions & 0 deletions .github/workflows/enos-run-admin-ui.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
---
name: Run Admin UI E2E Tests

on:
# Only trigger this working using workflow_call. It assumes that secrets are
# being inherited from the caller.
workflow_call:
inputs:
artifact-name:
required: true
type: string
edition:
required: true
type: string
docker-image-file:
required: true
type: string

jobs:
test:
runs-on: ${{ fromJSON(vars.RUNNER_LARGE) }}
continue-on-error: true
Comment thread
moduli marked this conversation as resolved.
strategy:
fail-fast: false # don't fail as that can skip required cleanup steps for jobs
matrix:
include:
- filter: 'e2e_ui_aws builder:crt protocol:http'
infra: 'aws'
- filter: 'e2e_ui_docker builder:crt'
infra: 'docker'
env:
GITHUB_TOKEN: ${{ secrets.SERVICE_USER_GITHUB_TOKEN }}
# Scenario variables
ENOS_VAR_aws_region: us-east-1
ENOS_VAR_aws_ssh_keypair_name: ${{ github.event.repository.name }}-ci-ssh-key
ENOS_VAR_aws_ssh_private_key_path: ./support/private_key.pem
ENOS_VAR_crt_bundle_path: ./support/boundary.zip
ENOS_VAR_test_email: ${{ secrets.SERVICE_USER_EMAIL }}
ENOS_VAR_boundary_edition: ${{ inputs.edition }}
ENOS_VAR_boundary_docker_image_file: ./support/boundary_docker_image.tar
steps:
- name: Set git config
run: |
git config --global url."https://oauth2:${{ secrets.SERVICE_USER_GITHUB_TOKEN }}@github.com".insteadOf "https://github.com"

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: '0'

- name: Set up Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 20
package-manager-cache: false

- name: Set up Terraform
uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4.0.0

- name: Set up Enos
uses: hashicorp/action-setup-enos@v1
with:
github-token: ${{ secrets.SERVICE_USER_GITHUB_TOKEN }}

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 # v5.1.0
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_CI }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_CI }}
aws-region: us-east-1
role-to-assume: ${{ secrets.AWS_ROLE_ARN_CI }}
role-skip-session-tagging: true
role-duration-seconds: 3600

- name: Install Vault CLI
run: |
wget https://releases.hashicorp.com/vault/1.17.6/vault_1.17.6_linux_amd64.zip -O /tmp/vault.zip
unzip -o -q /tmp/vault.zip -d "/usr/local/bin"

- name: Download Boundary Linux AMD64 bundle
id: download
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.1
with:
name: ${{ inputs.artifact-name }}
path: ./enos/support/downloads
Comment thread
moduli marked this conversation as resolved.

- name: Unzip and rename Boundary bundle
run: |
unzip -o -q ${{steps.download.outputs.download-path}}/*.zip -d "/usr/local/bin"
mv ${{steps.download.outputs.download-path}}/*.zip enos/support/boundary.zip

- name: Download Boundary Linux AMD64 docker image
if: contains(matrix.filter, 'docker')
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.1
id: download-docker
with:
name: ${{ inputs.docker-image-file }}
path: ./enos/support/downloads

- name: Rename docker image file
if: contains(matrix.filter, 'docker')
run: |
mv ${{ steps.download-docker.outputs.download-path }}/*.tar enos/support/boundary_docker_image.tar

- name: GPG setup
run: |
# Create a GPG key
KEY_PW=boundary
export KEY_PW
gpg --generate-key --batch <<eoGpgConf
%echo Started!
Key-Type: RSA
Key-Length: default
Subkey-Type: RSA
Name-Real: boundary
Name-Comment: default
Name-Email: default
Expire-Date: 0
Passphrase: $KEY_PW
%commit
%echo Done.
eoGpgConf

# Enable gpg-preset-passphrase so that key passwords can be saved
echo "allow-preset-passphrase" >> ~/.gnupg/gpg-agent.conf
gpg-connect-agent reloadagent /bye &>/dev/null

# Get information about the created keys
lines="$(gpg --list-secret-keys --with-colons --with-keygrip)"
KEY_ID=""
while read -r line
do
# Save the first key id to be used later
if [[ $line =~ "fpr"* ]]; then
if [[ $KEY_ID == "" ]]; then
KEY_ID="$(echo "$line" | sed -r 's/fpr|://g')"
fi
fi

# Cache the passphrases for the keys so passwords do not need to be entered
if [[ $line =~ "grp"* ]]; then
KEYGRIP_ID="$(echo "$line" | sed -r 's/grp|://g')"
/usr/lib/gnupg/gpg-preset-passphrase --preset -P "$KEY_PW" "$KEYGRIP_ID"
fi
done <<< "$lines"

# Trust the key
touch /tmp/test.txt
gpg -a --encrypt -r "$KEY_ID" --trust-model always --batch --yes /tmp/test.txt
echo "trusted-key $KEY_ID" >> ~/.gnupg/gpg.conf

# Initialize the password store
sudo apt-get update
sudo apt-get install -y pass
pass init "$KEY_ID" &>/dev/null

- name: Prepare scenario dependencies
id: prepare_scenario
run: |
mkdir -p ./enos/support
echo "${{ secrets.SSH_KEY_PRIVATE_CI }}" > ./enos/support/private_key.pem
chmod 600 ./enos/support/private_key.pem

- name: Set up test infra
id: infra
run: |
export ENOS_VAR_enos_user=$GITHUB_ACTOR && \
export ENOS_VAR_boundary_license="${{ secrets.BOUNDARY_ENT_LICENSE }}" && \
enos scenario launch --timeout 60m0s --chdir ./enos ${{matrix.filter}}

- name: Get SHA of UI version
id: get-ui-version
run: |
echo "Using UI Version $(cat ./internal/ui/VERSION)"
echo "sha=$(head -n 1 ./internal/ui/VERSION)" >> "$GITHUB_OUTPUT"
echo "repo=boundary-ui" >> "$GITHUB_OUTPUT"

- name: Checkout UI repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: hashicorp/${{ steps.get-ui-version.outputs.repo }}
ref: ${{ steps.get-ui-version.outputs.sha }}
path: support/src/ui
token: ${{ secrets.SERVICE_USER_GITHUB_TOKEN }}

- name: Set up pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
run_install: false
package_json_file: ./support/src/ui/package.json

- name: Install node dependencies
run: |
cd ./support/src/ui
pnpm install --frozen-lockfile

cd e2e-tests
pnpm playwright install --with-deps

- name: GH fix for localhost resolution
if: contains(matrix.filter, 'docker')
run: |
cat /etc/hosts && echo "-----------"
sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6 -localhost ip6-loopback/g' /etc/hosts
cat /etc/hosts
ssh -V
Comment thread
moduli marked this conversation as resolved.

- name: Run Tests
id: run-tests
run: |
# shellcheck disable=SC1090
source <(bash ./enos/scripts/test_e2e_env.sh)

cd ./support/src/ui/e2e-tests
pnpm run admin:ce:${{matrix.infra}} --reporter=html

- name: Split scenario name
if: ${{ failure() && steps.run-tests.outcome == 'failure' }}
id: split
run: |
SCENARIO=$(echo "${{ matrix.filter }}" | cut -d' ' -f1,3 | sed -e 's/:/_/g' | sed -e 's/ /_/g')
echo fragment="${SCENARIO}" >> "$GITHUB_OUTPUT"

- name: Upload Playwright report
if: ${{ failure() && steps.run-tests.outcome == 'failure' }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: playwright-report-${{ steps.split.outputs.fragment }}
path: ./support/src/ui/e2e-tests/playwright-report

- name: Clean up test infra
if: ${{ always() }}
continue-on-error: true
run: |
export ENOS_VAR_enos_user=$GITHUB_ACTOR && \
enos scenario destroy --timeout 60m0s --chdir ./enos ${{matrix.filter}}

- name: Send Slack message on failure
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
if: failure()
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOUNDARY_TEST_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_BOUNDARY_TEST_BOT_CHANNEL_ID }}
text: ":x: admin ui tests failed (${{ matrix.filter }}): ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Branch:* ${{ github.repository }}:${{ github.head_ref || github.ref_name }}"
47 changes: 21 additions & 26 deletions enos/enos-scenario-e2e-ui-aws.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ scenario "e2e_ui_aws" {
}

locals {
aws_ssh_private_key_path = abspath(var.aws_ssh_private_key_path)
boundary_install_dir = abspath(var.boundary_install_dir)
license_path = abspath(var.boundary_license_path != null ? var.boundary_license_path : joinpath(path.root, "./support/boundary.hclic"))
local_boundary_dir = var.local_boundary_dir != null ? abspath(var.local_boundary_dir) : null
local_boundary_ui_src_dir = var.local_boundary_ui_src_dir != null ? abspath(var.local_boundary_ui_src_dir) : null
aws_ssh_private_key_path = abspath(var.aws_ssh_private_key_path)
boundary_install_dir = abspath(var.boundary_install_dir)
license_path = abspath(var.boundary_license_path != null ? var.boundary_license_path : joinpath(path.root, "./support/boundary.hclic"))
build_path = {
"local" = "/tmp",
"crt" = var.crt_bundle_path == null ? null : abspath(var.crt_bundle_path)
Expand Down Expand Up @@ -194,27 +192,24 @@ scenario "e2e_ui_aws" {
]

variables {
debug_no_run = var.e2e_debug_no_run
alb_boundary_api_addr = step.create_boundary_cluster.alb_boundary_api_addr
auth_method_id = step.create_boundary_cluster.auth_method_id
auth_login_name = step.create_boundary_cluster.auth_login_name
auth_password = step.create_boundary_cluster.auth_password
local_boundary_dir = local.local_boundary_dir
local_boundary_ui_src_dir = local.local_boundary_ui_src_dir
aws_ssh_private_key_path = local.aws_ssh_private_key_path
target_address = step.create_targets_with_tag.target_private_ips[0]
target_user = "ubuntu"
target_port = "22"
vault_addr_public = step.create_vault_cluster.instance_addresses[0]
vault_addr_private = step.create_vault_cluster.instance_addresses_private[0]
vault_root_token = step.create_vault_cluster.vault_root_token
aws_access_key_id = step.iam_setup.access_key_id
aws_secret_access_key = step.iam_setup.secret_access_key
aws_host_set_filter = step.create_tag_inputs.tag_string
aws_host_set_ips = step.create_targets_with_tag.target_private_ips
worker_tag_egress = local.egress_tag
aws_region = var.aws_region
alb_cert = matrix.protocol == "https" ? step.create_boundary_cluster.alb_cert : ""
alb_boundary_api_addr = step.create_boundary_cluster.alb_boundary_api_addr
auth_method_id = step.create_boundary_cluster.auth_method_id
auth_login_name = step.create_boundary_cluster.auth_login_name
auth_password = step.create_boundary_cluster.auth_password
aws_ssh_private_key_path = local.aws_ssh_private_key_path
target_address = step.create_targets_with_tag.target_private_ips[0]
target_user = "ubuntu"
target_port = "22"
vault_addr_public = step.create_vault_cluster.instance_addresses[0]
vault_addr_private = step.create_vault_cluster.instance_addresses_private[0]
vault_root_token = step.create_vault_cluster.vault_root_token
aws_access_key_id = step.iam_setup.access_key_id
aws_secret_access_key = step.iam_setup.secret_access_key
aws_host_set_filter = step.create_tag_inputs.tag_string
aws_host_set_ips = step.create_targets_with_tag.target_private_ips
worker_tag_egress = local.egress_tag
aws_region = var.aws_region
alb_cert = matrix.protocol == "https" ? step.create_boundary_cluster.alb_cert : ""
}
}

Expand Down
Loading
Loading