Compare commits

..
1 Commits
Author SHA1 Message Date
hashicc cd3fc5cea7 fix: 🐛 apply .sr-only fix to all instances 2025-12-11 10:08:17 -08:00
2311 changed files with 14832 additions and 22644 deletions

No files matched your search

+2 -1
View File
@@ -2,12 +2,13 @@ schema_version = 1
project {
license = "BUSL-1.1"
copyright_year = 2021
copyright_year = 2024
# (OPTIONAL) A list of globs that should not have copyright/license headers.
# Supports doublestar glob patterns for more flexibility in defining which
# files or folders should be ignored
header_ignore = [
".github/**",
".husky/**",
"**/node_modules/**",
"**/dist/**",
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright IBM Corp. 2021, 2026
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
contact_links:
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright IBM Corp. 2021, 2026
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
addons:
+2 -3
View File
@@ -1,8 +1,7 @@
#!/usr/bin/env bash
# Copyright IBM Corp. 2021, 2026
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
set -euo pipefail
# Configure Git
@@ -92,4 +91,4 @@ gh pr create \
-b "${BASE_BRANCH/oss\//} upstream merge of (${SHA::7})"
gh pr merge --auto --merge
# This PR will be need to be approved manually
# This PR will be need to be approved manually
+11 -11
View File
@@ -13,18 +13,18 @@ jobs:
runs-on: ${{ fromJSON(vars.RUNNER) }}
timeout-minutes: 40
steps:
- uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2
- uses: browser-actions/setup-chrome@b94431e051d1c52dcbe9a7092a4f10f827795416 # v2.1.0
with:
install-dependencies: true
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
node-version: 24
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
with:
cache: true
cache_dependency_path: '**/pnpm-lock.yaml'
run_install: false
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install
- name: Run a11y tests
env:
@@ -37,11 +37,11 @@ jobs:
jq -s 'map(.[])' ./ui/admin/ember-a11y-report/*.json > ember-a11y-reports/admin.json
jq -s 'map(.[])' ./ui/desktop/ember-a11y-report/*.json > ember-a11y-reports/desktop.json
- name: Output ember a11y test report summary (admin)
run: 'cat ember-a11y-reports/admin.json | jq "map({moduleName,testName,routes,urls,violations: .violations | map({id, nodes: .nodes | map({failureSummary, targets: .[] | .[]? | .relatedNodes? | .[]? | .target? })}) })"'
run: 'cat ember-a11y-reports/admin.json | jq "map({moduleName,testName,routes,urls,violations: .violations | map({id, nodes: .nodes | map({failureSummary, targets: .[].[]?.relatedNodes?.[]?.target? })}) })"'
- name: Output ember a11y test report summary (desktop)
run: 'cat ember-a11y-reports/desktop.json | jq "map({moduleName,testName,routes,urls,violations: .violations | map({id, nodes: .nodes | map({failureSummary, targets: .[] | .[]? | .relatedNodes? | .[]? | .target? })}) })"'
run: 'cat ember-a11y-reports/desktop.json | jq "map({moduleName,testName,routes,urls,violations: .violations | map({id, nodes: .nodes | map({failureSummary, targets: .[].[]?.relatedNodes?.[]?.target? })}) })"'
- name: Upload ember a11y reports
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: ember-a11y-reports
path: ./ember-a11y-reports
+35 -35
View File
@@ -11,40 +11,40 @@ jobs:
name: Install dependencies
runs-on: ${{ fromJSON(vars.RUNNER) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
node-version: 24
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
with:
cache: true
cache_dependency_path: '**/pnpm-lock.yaml'
run_install: false
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --frozen-lockfile
build-admin-ui-oss:
name: Build Admin UI OSS
needs: [dependencies]
runs-on: ${{ fromJSON(vars.RUNNER) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Build
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
run_install: false
cache: true
cache_dependency_path: '**/pnpm-lock.yaml'
- name: Build
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --offline
- run: pnpm run build:ui:admin:oss
- name: Upload artifact admin-ui
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: admin-ui
path: ./ui/admin/dist/
- name: Upload artifact OSS admin UI
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: admin-ui-oss
path: ./ui/admin/dist/
@@ -53,20 +53,20 @@ jobs:
needs: [dependencies]
runs-on: ${{ fromJSON(vars.RUNNER) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Build
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
run_install: false
cache: true
cache_dependency_path: '**/pnpm-lock.yaml'
- name: Build
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --offline
- run: pnpm run build:ui:admin:enterprise
- name: Upload artifact enterprise admin UI
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: admin-ui-ent
path: ./ui/admin/dist/
@@ -75,20 +75,20 @@ jobs:
needs: [dependencies]
runs-on: ${{ fromJSON(vars.RUNNER) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Build
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
run_install: false
cache: true
cache_dependency_path: '**/pnpm-lock.yaml'
- name: Build
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --offline
- run: pnpm run build:ui:admin:hcp
- name: Upload artifact HCP admin UI
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: admin-ui-hcp
path: ./ui/admin/dist/
+1 -6
View File
@@ -30,12 +30,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
+2 -2
View File
@@ -6,7 +6,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
# Ref and repository aren't normally needed, this is a workaround for a bug in auto commit
with:
ref: ${{ github.event.pull_request.head.ref }}
@@ -14,6 +14,6 @@ jobs:
- uses: hashicorp/setup-copywrite@32638da2d4e81d56a0764aa1547882fc4d209636 # v1.1.3
- name: Add missing Copyright Headers
run: copywrite headers
- uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
- uses: stefanzweifel/git-auto-commit-action@28e16e81777b558cc906c8750092100bbb34c5e3 # v7.0.0
with:
commit_message: Add missing copyright headers
+107
View File
@@ -0,0 +1,107 @@
on:
issues:
types: [opened, closed, deleted, reopened]
pull_request_target:
types: [opened, closed, reopened]
issue_comment: # Also triggers when commenting on a PR from the conversation view
types: [created]
workflow_dispatch:
name: Jira Sync
jobs:
sync:
runs-on: ${{ fromJSON(vars.RUNNER) }}
name: Jira sync
steps:
- name: Check if community user
if: github.event.action == 'opened'
id: boundary-team-role
run: |
TEAM=boundary
ROLE="$(gh api orgs/hashicorp/teams/${TEAM}/memberships/${{ github.actor }} | jq -r '.role | select(.!=null)')"
if [[ -n ${ROLE} ]]; then
echo "Actor ${{ github.actor }} is a ${TEAM} team member, skipping ticket creation"
else
echo "Actor ${{ github.actor }} is not a ${TEAM} team member"
fi
echo "role=${ROLE}" >> $GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ secrets.JIRA_SYNC_GITHUB_TOKEN }}
- name: Set ticket type
if: github.event.action == 'opened' && !steps.boundary-team-role.outputs.role
id: set-ticket-type
run: |
if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
echo "type=PR" >> $GITHUB_OUTPUT
else
echo "type=ISS" >> $GITHUB_OUTPUT
fi
- name: Create ticket
if: github.event.action == 'opened' && !steps.boundary-team-role.outputs.role
uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
with:
project: ICU
issuetype: "GH Issue"
summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.type }} #${{ github.event.issue.number || github.event.pull_request.number }}]: ${{ github.event.issue.title || github.event.pull_request.title }}"
description: "${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created from GitHub Action for ${{ github.event.issue.html_url || github.event.pull_request.html_url }}, from ${{ github.actor }}_"
# customfield_10089 is Issue Link custom field
# customfield_10091 is team custom field
extraFields: '{"customfield_10089": "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"}'
- name: Search
if: github.event.action != 'opened'
id: search
uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
with:
# cf[10089] is Issue Link custom field
jql: 'issuetype = "GH Issue" and cf[10089]="${{ github.event.issue.html_url || github.event.pull_request.html_url }}"'
- name: Sync comment
if: github.event.action == 'created' && steps.search.outputs.issue
uses: tomhjp/gh-action-jira-comment@6eb6b9ead70221916b6badd118c24535ed220bd9 # v0.2.0
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
with:
issue: ${{ steps.search.outputs.issue }}
comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}"
- name: Transitions
id: transitions
if: steps.search.outputs.issue
run: |
if [[ "${{ github.event.action }}" == "closed" || "${{ github.event.action }}" == "deleted" ]]; then
echo "Closing ticket"
echo "name=Done" >> "$GITHUB_OUTPUT"
elif [[ "${{ github.event.action }}" == "reopened" ]]; then
echo "Reopening ticket"
echo "name=Reopen" >> "$GITHUB_OUTPUT"
fi
# Transition issue API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-transitions-post
- name: Transition ticket
if: steps.transitions.outputs.name
run: |
transitions="$(curl --silent \
--url "${{ secrets.JIRA_BASE_URL }}rest/api/3/issue/${{ steps.search.outputs.issue }}/transitions" \
--user "${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }}" \
--header "Accept: application/json")"
id="$(echo "${transitions}" | jq -r '.transitions[] | select(.name == "${{ steps.transitions.outputs.name }}") | .id')"
curl --silent \
--url "${{ secrets.JIRA_BASE_URL }}rest/api/3/issue/${{ steps.search.outputs.issue }}/transitions" \
--user "${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }}" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "$(printf '{"transition": {"id": "%s"}}' "${id}")"
+1 -1
View File
@@ -6,6 +6,6 @@ jobs:
triage:
runs-on: ${{ fromJSON(vars.RUNNER) }}
steps:
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
- uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
+29 -29
View File
@@ -6,15 +6,15 @@ jobs:
name: Install dependencies
runs-on: ${{ fromJSON(vars.RUNNER) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
node-version: 24
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
with:
cache: true
cache_dependency_path: '**/pnpm-lock.yaml'
run_install: false
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --frozen-lockfile
compliance:
@@ -22,15 +22,15 @@ jobs:
needs: [dependencies]
runs-on: ${{ fromJSON(vars.RUNNER) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
run_install: false
cache: true
cache_dependency_path: '**/pnpm-lock.yaml'
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --offline
- run: pnpm run compliance:licenses
@@ -40,15 +40,15 @@ jobs:
runs-on: ${{ fromJSON(vars.RUNNER) }}
timeout-minutes: 5
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
run_install: false
cache: true
cache_dependency_path: '**/pnpm-lock.yaml'
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --offline
- run: pnpm lint
@@ -58,17 +58,17 @@ jobs:
runs-on: ${{ fromJSON(vars.RUNNER) }}
timeout-minutes: 15
steps:
- uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2
- uses: browser-actions/setup-chrome@b94431e051d1c52dcbe9a7092a4f10f827795416 # v2.1.0
with:
install-dependencies: true
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
run_install: false
cache: true
cache_dependency_path: '**/pnpm-lock.yaml'
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- run: pnpm install --offline
- run: pnpm test
+1 -1
View File
@@ -7,7 +7,7 @@ jobs:
runs-on: ${{ fromJSON(vars.RUNNER) }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
- run: |
+59 -192
View File
@@ -3,6 +3,13 @@ name: Test E2E Admin UI
on:
pull_request:
types: [labeled, opened, synchronize, reopened]
paths:
- 'ui/admin/**'
- 'e2e-tests/*'
- 'e2e-tests/api-client/**'
- 'e2e-tests/helpers/**'
- 'e2e-tests/admin/**'
- '.github/workflows/test-e2e-admin-ui.yaml'
workflow_dispatch:
inputs:
boundary-enterprise-branch:
@@ -17,95 +24,60 @@ on:
type: string
jobs:
setup:
name: setup matrix
# don't need to run e2e tests on ce -> ent merges since tests were already
# run in the ce branch, and there are currently no code differences between
# the two repos
if: github.actor != 'hc-github-team-secure-boundary'
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Set matrix
id: set-matrix
run: |
BOUNDARY_BRANCH="${{ github.event.inputs.boundary-branch || 'main' }}"
ENT_BRANCH="${{ github.event.inputs.boundary-enterprise-branch || 'main' }}"
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
matrix=$(jq -cn --arg branch "$BOUNDARY_BRANCH" '{
browser: ["chromium", "firefox", "webkit"],
include: [{
boundary_edition: "community",
github_repo: "hashicorp/boundary",
folder_name: "boundary",
boundary_edition_short: "oss",
enos_scenario: "e2e_ui_docker",
test_command: "admin:ce:docker",
boundary_branch: $branch
}]
}')
else
matrix=$(jq -cn --arg branch "$ENT_BRANCH" '{
browser: ["chromium", "firefox", "webkit"],
include: [{
boundary_edition: "enterprise",
github_repo: "hashicorp/boundary-enterprise",
folder_name: "boundary-enterprise",
boundary_edition_short: "ent",
enos_scenario: "e2e_ui_docker_ent",
test_command: "admin:ent:docker",
boundary_branch: $branch
}]
}')
fi
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
test:
name: test
needs: setup
runs-on: ${{ fromJSON(vars.RUNNER_UBUNTU_22) }}
strategy:
matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
matrix:
include:
- boundary_edition: community
github_repo: hashicorp/boundary
folder_name: boundary
boundary_edition_short: oss
enos_scenario: e2e_ui_docker
test_command: admin:ce:docker
boundary_branch: ${{ github.event.inputs.boundary-branch || 'main' }}
- boundary_edition: enterprise
github_repo: hashicorp/boundary-enterprise
folder_name: boundary-enterprise
boundary_edition_short: ent
enos_scenario: e2e_ui_docker_ent
test_command: admin:ent:docker
boundary_branch: ${{ github.event.inputs.boundary-enterprise-branch || 'main' }}
fail-fast: false
env:
ENOS_VAR_e2e_debug_no_run: true
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
- name: Set up pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
cache: true
cache_dependency_path: |
pnpm-lock.yaml
ui/desktop/electron-app/pnpm-lock.yaml
run_install: false
- name: Set up Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: "pnpm"
cache-dependency-path: |
pnpm-lock.yaml
ui/desktop/electron-app/pnpm-lock.yaml
- name: Set up Terraform
uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd
- name: Set up Enos
uses: hashicorp/action-setup-enos@6ec106c8f809fe645162d73bea565c65f3269907
uses: hashicorp/action-setup-enos@39a8f388434bea5eeba6649b99aa9949a55a1150
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- 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
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
unzip -o -q /tmp/vault.zip -d /usr/local/bin
elif [[ "${{ github.repository }}" == "hashicorp/boundary-ui-enterprise" ]]; then
unzip -o -q /tmp/vault.zip -d "$HOME/bin"
fi
wget https://releases.hashicorp.com/vault/1.12.2/vault_1.12.2_linux_amd64.zip -O /tmp/vault.zip
unzip /tmp/vault.zip -d /usr/local/bin
- name: GPG setup
run: |
@@ -154,12 +126,10 @@ jobs:
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: Checkout ${{ matrix.folder_name }} repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: ${{ matrix.github_repo }}
path: support/src/${{ matrix.folder_name }}
@@ -168,129 +138,32 @@ jobs:
- name: GH fix for localhost resolution
run: |
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
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
fi
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
echo "127.0.0.1 localhost boundary" | sudo tee -a /etc/hosts
echo "127.0.0.1 localhost worker" | sudo tee -a /etc/hosts
echo "127.0.0.1 localhost vault" | sudo tee -a /etc/hosts
- name: Set git config
run: |
git config --global url."https://oauth2:${{ secrets.ELEVATED_GITHUB_TOKEN }}@github.com".insteadOf "https://github.com"
- name: Install Dependencies and Browsers
- name: Install node dependencies
run: |
# Block Playwright from doing anything during the pnpm install
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 pnpm install --frozen-lockfile
pnpm install --frozen-lockfile
cd e2e-tests
# Install browsers and dependencies based on the repository
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
pnpm playwright install --with-deps
elif [[ "${{ github.repository }}" == "hashicorp/boundary-ui-enterprise" ]]; then
# Use raw apt-get to install system libraries without npx
sudo apt-get install -y \
libnss3 \
libnspr4 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libcups2 \
libdrm2 \
libdbus-1-3 \
libxcb1 \
libxkbcommon0 \
libx11-6 \
libxcomposite1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxrandr2 \
libgbm1 \
libpango-1.0-0 \
libcairo2 \
libasound2 \
libgtk-4-1 \
libgraphene-1.0-0 \
libevent-2.1-7 \
libopus0 \
libgstreamer-plugins-base1.0-0 \
libgstreamer-plugins-good1.0-0 \
libgstreamer-gl1.0-0 \
libgstreamer-plugins-bad1.0-0 \
libflite1 \
libwebpdemux2 \
libavif13 \
libwebpmux3 \
libmanette-0.2-0 \
libenchant-2-2 \
libhyphen0 \
libsecret-1-0 \
libwoff1 \
libx264-163 \
libsoup-3.0-0 \
gstreamer1.0-libav \
libicu70 \
libegl1 \
libepoxy0 \
libevdev2 \
libffi7 \
libfontconfig1 \
libfreetype6 \
libgdk-pixbuf-2.0-0 \
libgles2 \
libglib2.0-0 \
libglx0 \
libgstreamer1.0-0 \
libgudev-1.0-0 \
libharfbuzz-icu0 \
libharfbuzz0b \
libjpeg-turbo8 \
liblcms2-2 \
libnotify4 \
libopengl0 \
libopenjp2-7 \
libpng16-16 \
libproxy1v5 \
libwayland-client0 \
libwayland-egl1 \
libwayland-server0 \
libxml2 \
libxslt1.1 \
libatomic1
# Install the browser executables
pnpm playwright install
fi
- name: Determine Go version
id: get-go-version
run: |
echo "Building with Go $(cat ./support/src/${{matrix.folder_name}}/.go-version)"
echo "go-version=$(cat ./support/src/${{matrix.folder_name}}/.go-version)" >> "$GITHUB_OUTPUT"
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: ${{ steps.get-go-version.outputs.go-version }}
cache: false
pnpm playwright install --with-deps
- name: Set up test infra
id: infra
run: |
ssh-keygen -N '' -t ed25519 -f ~/.ssh/github_enos
mkdir -p ./enos/terraform-plugin-cache
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
echo ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} > ./support/src/${{matrix.folder_name}}/internal/ui/VERSION
export ENOS_VAR_ui_build_override="oss"
elif [[ "${{ github.repository }}" == "hashicorp/boundary-ui-enterprise" ]]; then
echo ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} > ./support/src/${{matrix.folder_name}}/internal/ui/VERSION_ent
export ENOS_VAR_ui_build_override="enterprise"
fi
echo ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} > ./support/src/${{matrix.folder_name}}/internal/ui/VERSION
export ENOS_VAR_ui_build_override="oss" && \
export ENOS_VAR_boundary_edition=${{ matrix.boundary_edition_short }} && \
export ENOS_VAR_enos_user=$GITHUB_ACTOR && \
export ENOS_VAR_aws_ssh_private_key_path=~/.ssh/github_enos && \
@@ -299,30 +172,24 @@ jobs:
- name: Move boundary binary
run: |
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
mv ./support/src/${{matrix.folder_name}}/bin/boundary /usr/local/bin/
elif [[ "${{ github.repository }}" == "hashicorp/boundary-ui-enterprise" ]]; then
mv ./support/src/${{matrix.folder_name}}/bin/boundary $HOME/bin
fi
mv ./support/src/${{matrix.folder_name}}/bin/boundary /usr/local/bin/
boundary version
- name: Run Tests
run: |
source <(bash ./support/src/${{matrix.folder_name}}/enos/scripts/test_e2e_env.sh)
cd e2e-tests
pnpm run ${{ matrix.test_command }} --project=${{ matrix.browser}} --reporter=html
pnpm run ${{ matrix.test_command }} --reporter=html
- name: Upload Playwright report
if: ${{ failure() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: playwright-report-${{ matrix.boundary_edition }}-${{ matrix.browser }}
name: playwright-report-${{ matrix.boundary_edition }}
path: e2e-tests/playwright-report
- name: Clean up test infra
if: ${{ always() }}
continue-on-error: true
run: |
export ENOS_VAR_boundary_edition=${{ matrix.boundary_edition_short }} && \
export ENOS_VAR_enos_user=$GITHUB_ACTOR && \
@@ -330,11 +197,11 @@ jobs:
enos scenario destroy --timeout 60m0s --chdir ./support/src/${{matrix.folder_name}}/enos ${{matrix.enos_scenario}} builder:local
- name: Send Slack message on failure
uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3
if: ${{ failure() && github.repository == 'hashicorp/boundary-ui-enterprise' }}
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
if: ${{ failure() && github.repository == 'hashicorp/boundary-ui' }}
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
text: ":x: admin ui e2e tests (${{ matrix.boundary_edition }}:${{ matrix.browser }}) failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Branch:* ${{ github.repository }}:${{ github.head_ref || github.ref_name }}"
text: ":x: admin ui e2e tests failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Branch:* ${{ github.repository }}:${{ github.head_ref }}"
+46 -102
View File
@@ -3,182 +3,126 @@ name: Test E2E Desktop Client
on:
pull_request:
types: [labeled, opened, synchronize, reopened]
paths:
- 'ui/desktop/**'
- 'e2e-tests/*'
- 'e2e-tests/api-client/**'
- 'e2e-tests/helpers/**'
- 'e2e-tests/desktop/**'
- '.github/workflows/test-e2e-desktop.yaml'
workflow_dispatch:
inputs:
boundary-enterprise-branch:
description: 'Branch of boundary-enterprise to test against (default to main)'
required: true
default: 'main'
type: string
boundary-ui-enterprise-branch:
description: 'Branch of boundary-ui-enterprise to test against (default to main)'
required: true
default: 'main'
type: string
jobs:
test:
name: test
# don't need to run e2e tests on ce -> ent merges since tests were already
# run in the ce branch, and there are currently no code differences between
# the two repos
# desktop client e2e tests only run enterprise tests, so only run in boundary-ui-enterprise
if: github.actor != 'hc-github-team-secure-boundary' && github.repository == 'hashicorp/boundary-ui-enterprise'
runs-on: ${{ fromJSON(vars.RUNNER_UBUNTU_22) }}
env:
ENOS_VAR_boundary_edition: "ent"
ENOS_VAR_e2e_debug_no_run: true
SETUP_CLI: true
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
- name: Set up pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 #v6.0.8
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
with:
cache: true
cache_dependency_path: |
pnpm-lock.yaml
ui/desktop/electron-app/pnpm-lock.yaml
run_install: false
- name: Set up Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20
cache: "pnpm"
cache-dependency-path: |
pnpm-lock.yaml
ui/desktop/electron-app/pnpm-lock.yaml
- name: Set up Terraform
uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd
- name: Set up Enos
uses: hashicorp/action-setup-enos@6ec106c8f809fe645162d73bea565c65f3269907
uses: hashicorp/action-setup-enos@39a8f388434bea5eeba6649b99aa9949a55a1150
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- 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
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
unzip -o -q /tmp/vault.zip -d /usr/local/bin
elif [[ "${{ github.repository }}" == "hashicorp/boundary-ui-enterprise" ]]; then
unzip -o -q /tmp/vault.zip -d "$HOME/bin"
fi
wget https://releases.hashicorp.com/vault/1.12.2/vault_1.12.2_linux_amd64.zip -O /tmp/vault.zip
unzip /tmp/vault.zip -d /usr/local/bin
# TODO: We should consider modifying to also build CE binary. For now
# building ENT binary using most recent UI commit is sufficient.
- name: Checkout boundary-enterprise
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: hashicorp/boundary-enterprise
ref: ${{ github.event.inputs.boundary-enterprise-branch || 'main' }}
# ref: ${{ github.event.inputs.boundary-enterprise-branch }}
path: support/src/boundary-enterprise
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
- name: Checkout boundary-ui-enterprise
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: hashicorp/boundary-ui-enterprise
ref: ${{ github.event.inputs.boundary-ui-enterprise-branch || 'main' }}
path: support/src/boundary-ui-enterprise
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
- name: Use boundary-ui-enterprise commit SHA for building binary
run: |
cd support/src/boundary-ui-enterprise
git rev-parse HEAD > ../boundary-enterprise/internal/ui/VERSION_ent
- name: GH fix for localhost resolution
run: |
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
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
fi
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
- name: Set git config
echo "127.0.0.1 localhost boundary" | sudo tee -a /etc/hosts
echo "127.0.0.1 localhost worker" | sudo tee -a /etc/hosts
echo "127.0.0.1 localhost vault" | sudo tee -a /etc/hosts
# TODO: Build image ourselves in case we don't want to use latest?
- name: Get Boundary docker image
run: |
git config --global url."https://oauth2:${{ secrets.ELEVATED_GITHUB_TOKEN }}@github.com".insteadOf "https://github.com"
- name: Determine Go version
id: get-go-version
run: |
echo "Building with Go $(cat ./support/src/boundary-enterprise/.go-version)"
echo "go-version=$(cat ./support/src/boundary-enterprise/.go-version)" >> "$GITHUB_OUTPUT"
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: ${{ steps.get-go-version.outputs.go-version }}
cache: false
docker pull hashicorp/boundary-enterprise:latest
docker save hashicorp/boundary-enterprise:latest | gzip > /tmp/boundary-enterprise.zip
- name: Set up test infra
id: infra
run: |
ssh-keygen -N '' -t ed25519 -f ~/.ssh/github_enos
mkdir -p ./enos/terraform-plugin-cache
export ENOS_VAR_ui_build_override="ent" && \
export ENOS_VAR_boundary_edition="ent" && \
export ENOS_VAR_enos_user=$GITHUB_ACTOR && \
export ENOS_VAR_aws_ssh_private_key_path=~/.ssh/github_enos && \
export ENOS_VAR_boundary_license="${{ secrets.BOUNDARY_ENT_LICENSE }}" && \
enos scenario launch --timeout 60m0s --chdir ./support/src/boundary-enterprise/enos e2e_ui_docker_ent builder:local
- name: Move boundary binary
run: |
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
mv ./support/src/boundary-enterprise/bin/boundary /usr/local/bin/
elif [[ "${{ github.repository }}" == "hashicorp/boundary-ui-enterprise" ]]; then
mv ./support/src/boundary-enterprise/bin/boundary $HOME/bin
fi
boundary version
export ENOS_VAR_boundary_docker_image_file=/tmp/boundary-enterprise.zip && \
enos scenario launch --timeout 60m0s --chdir ./support/src/boundary-enterprise/enos e2e_ui_docker_ent builder:crt
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
cd e2e-tests
if [[ "${{ github.repository }}" == "hashicorp/boundary-ui" ]]; then
pnpm playwright install --with-deps
elif [[ "${{ github.repository }}" == "hashicorp/boundary-ui-enterprise" ]]; then
# playwright dependencies can't be installed on a self-hosted runner
# due to permission issues
pnpm playwright install
sudo apt update -qq
sudo apt install xvfb -y
fi
pnpm playwright install --with-deps
# Runner is headless so we need to enable a display to run the client
- name: Run Tests
run: |
source <(bash ./support/src/boundary-enterprise/enos/scripts/test_e2e_env.sh)
cd e2e-tests
export DISPLAY=:99
Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 &
sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 &
pnpm run desktop
- name: Upload Playwright report
if: ${{ failure() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: playwright-report
path: e2e-tests/playwright-report
- name: Clean up test infra
if: ${{ always() }}
continue-on-error: true
run: |
export ENOS_VAR_enos_user=$GITHUB_ACTOR && \
export ENOS_VAR_aws_ssh_private_key_path=~/.ssh/github_enos && \
enos scenario destroy --timeout 60m0s --chdir ./support/src/boundary-enterprise/enos e2e_ui_docker_ent builder:local
enos scenario destroy --timeout 60m0s --chdir ./support/src/boundary-enterprise/enos e2e_ui_docker_ent builder:crt
- name: Send Slack message on failure
uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3
if: ${{ failure() && github.repository == 'hashicorp/boundary-ui-enterprise' }}
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
if: ${{ failure() && github.repository == 'hashicorp/boundary-ui' }}
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
text: ":x: desktop client e2e tests failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Branch:* ${{ github.repository }}:${{ github.head_ref || github.ref_name }}"
text: ":x: desktop client e2e tests failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Branch:* ${{ github.repository }}:${{ github.head_ref }}"
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
trigger-gha-release:
runs-on: ${{ fromJSON(vars.RUNNER) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Release description
run: |
echo "Triggering release with a TAG ${GITHUB_REF#refs/tags/}"
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright IBM Corp. 2021, 2026
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
url_license = "https://github.com/hashicorp/boundary-ui/blob/main/LICENSE"
+7 -7
View File
@@ -3,21 +3,21 @@ License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.
Parameters
Licensor: International Business Machines Corporation (IBM)
Licensed Work: The Licensed Work is (c) 2024 IBM Corp.
Licensor: HashiCorp, Inc.
Licensed Work: The Licensed Work is (c) 2024 HashiCorp, Inc.
Additional Use Grant: You may make production use of the Licensed Work, provided
Your use does not include offering the Licensed Work to third
parties on a hosted or embedded basis in order to compete with
IBM Corp's paid version(s) of the Licensed Work. For purposes
HashiCorp's paid version(s) of the Licensed Work. For purposes
of this license:
A "competitive offering" is a Product that is offered to third
parties on a paid basis, including through paid support
arrangements, that significantly overlaps with the capabilities
of IBM Corp's paid version(s) of the Licensed Work. If Your
of HashiCorp's paid version(s) of the Licensed Work. If Your
Product is not a competitive offering when You first make it
generally available, it will not become a competitive offering
later due to IBM Corp releasing a new version of the Licensed
later due to HashiCorp releasing a new version of the Licensed
Work with additional capabilities. In addition, Products that
are not provided on a paid basis are not competitive.
@@ -33,10 +33,10 @@ Additional Use Grant: You may make production use of the Licensed Work, provided
Hosting or using the Licensed Work(s) for internal purposes
within an organization is not considered a competitive
offering. IBM Corp considers your organization to include all
offering. HashiCorp considers your organization to include all
of your affiliates under common control.
For binding interpretive guidance on using IBM Corp products
For binding interpretive guidance on using HashiCorp products
under the Business Source License, please visit our FAQ.
(https://www.hashicorp.com/license-faq)
Change Date: Four years from the date the Licensed Work is published.
+14
View File
@@ -0,0 +1,14 @@
# unconventional js
/blueprints/*/files/
# compiled output
/declarations/
/dist/
# misc
/coverage/
!.*
.*/
# ember-try
/.node_modules.ember-try/
+69
View File
@@ -0,0 +1,69 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
'use strict';
module.exports = {
root: true,
parser: '@babel/eslint-parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
// This is specific babel-config. If grows consider creating a babel config file
requireConfigFile: false,
babelOptions: {
plugins: [
['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }],
],
},
// end of babel-config
},
plugins: ['ember'],
extends: ['eslint:recommended', 'plugin:ember/recommended', 'prettier'],
env: {
browser: true,
},
rules: {
curly: ['error', 'multi-line', 'consistent'],
'ember/no-get': 'off',
'ember/no-get-with-default': 'off',
'ember/no-computed-properties-in-native-classes': 'off',
'ember/no-assignment-of-untracked-properties-used-in-tracking-contexts':
'off',
},
overrides: [
// node files
{
files: [
'./.eslintrc.js',
'./.prettierrc.js',
'./.template-lintrc.js',
'./ember-cli-build.js',
'./index.js',
'./testem.js',
'./blueprints/*/index.js',
'./config/**/*.js',
'./tests/dummy/config/**/*.js',
'./broccoli-plugins/**/*.js',
],
parserOptions: {
sourceType: 'script',
},
env: {
browser: false,
node: true,
},
extends: ['plugin:n/recommended'],
},
{
// test files
files: ['tests/**/*-test.{js,ts}'],
extends: ['plugin:qunit/recommended'],
rules: {
'qunit/require-expect': [2, 'except-simple'],
},
},
],
};
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+5 -38
View File
@@ -21,50 +21,17 @@ This addon contains the API data access layer for Boundary.
## Add API to an App
Add this addon to an Ember application's `devDependencies` as:
`"api": "workspace:*"`, for applications included in this monorepo.
`"api": "workspace:*"`, for applications included in this monorepo.
This addon also includes Mirage mocks. To include the `miragejs` dependency and this addon's mirage handlers configure the consuming app's `config/environment.js`
Since this addon also includes Mirage mocks, be sure to install
`ember-cli-mirage` and add the following config to your UI project:
```js
mirage: {
enabled: true
'ember-cli-mirage': {
directory: '../../addons/api/mirage'
}
```
Include `miragejs` and any api addon `peerDependencies` used by the mirage as dev dependencies in the consuming app,
eg: `@faker-js/faker`, otherwise mirage handler code might fail with an error.
To have mirage start and intercept requests when the application starts:
1. Add the `@embroider/macros` dependency to your application
2. Configure `@embroider/macros` with `startMirageWithApp` based on app's config within `ember-cli-build.js`:
```js
// ember-cli-build.js
module.exports = async function (defaults) {
// load the app's config
const { EMBER_ENV } = process.env;
var config = require('./config/environment')(EMBER_ENV);
const app = new EmberApp(defaults, {
'@embroider/macros': {
setOwnConfig: {
startMirageWithApp: config.mirage?.enabled ?? false
},
},
});
}
```
3. Finally, use the `@embroider/macros` config value for `startMirageWithApp` in `app/app.js` to conditionally start mirage:
```js
import { macroCondition, importSync, getOwnConfig, isTesting } from '@embroider/macros';
if (macroCondition(getOwnConfig().startMirageWithApp && !isTesting())) {
const startServer = importSync('[name of host app]/mirage/config').default;
startServer({});
}
```
## Installation
See monorepo README for installation instructions.
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -11,7 +11,7 @@ import { underscore } from '@ember/string';
/**
* This test helper can be used to help setup your sinon stubs in your tests.
* Must be called after setupMirage and setupDesktopContextBridgeApiMock in tests.
* Must be called after setupMirage.
*
* ```js
* import setupStubs from 'api/test-support/handlers/cache-daemon-search';
@@ -19,15 +19,14 @@ import { underscore } from '@ember/string';
* module('Acceptance | my test', function(hooks) {
* setupApplicationTest(hooks);
* setupMirage(hooks);
* setupDesktopContextBridgeApiMock(hooks);
* setupStubs(hooks);
*
* // add your actual tests here
* });
* ```
*
* This will setup a stub for window.desktop.daemon.searchCacheDaemon and include
* helper methods to help setup what the cache daemon search command returns.
* This will setup a stub for the IPC service and include helper methods to
* help setup what the cache daemon search command returns.
*
* @module Test Helpers
* @public
@@ -36,6 +35,9 @@ export default function setupStubs(hooks) {
let stubTypes = [];
hooks.beforeEach(function () {
const ipcService = this.owner.lookup('service:ipc');
this.ipcStub = sinon.stub(ipcService, 'invoke');
/**
* We aim to still use mirage data when stubbing out the cache daemon
* search. However, the handler expects the search data to be raw JSON from
@@ -54,32 +56,34 @@ export default function setupStubs(hooks) {
stubTypes = types;
types.forEach((type, i) => {
this.searchCacheDaemonStub.onCall(i).callsFake(() => {
let models;
let resourceName;
if (typeOf(type) === 'object') {
models = type.func();
resourceName = type.resource;
} else {
models = this.server.schema[type].all().models;
resourceName = type;
}
this.ipcStub
.withArgs('searchCacheDaemon')
.onCall(i)
.callsFake(() => {
let models;
let resourceName;
if (typeOf(type) === 'object') {
models = type.func();
resourceName = type.resource;
} else {
models = this.server.schema[type].all().models;
resourceName = type;
}
return {
[underscore(resourceNames[singularize(resourceName)])]: models.map(
(model) => {
// Use internal serializer to serialize the model correctly
// according to our mirage serializers
const modelData =
this.server.serializerOrRegistry.serialize(model);
return {
[underscore(resourceNames[singularize(resourceName)])]:
models.map((model) => {
// Use internal serializer to serialize the model correctly
// according to our mirage serializers
const modelData =
this.server.serializerOrRegistry.serialize(model);
// Serialize the data properly to standard JSON as that is what
// we're expecting from the cache daemon response
return JSON.parse(JSON.stringify(modelData));
},
),
};
});
// Serialize the data properly to standard JSON as that is what
// we're expecting from the cache daemon response
return JSON.parse(JSON.stringify(modelData));
}),
};
});
});
};
});
@@ -87,19 +91,22 @@ export default function setupStubs(hooks) {
hooks.afterEach(function () {
// Verify the number of mocks we set up match with how
// many times the cache daemon was called with
sinon.assert.callCount(this.searchCacheDaemonStub, stubTypes.length);
sinon.assert.callCount(
this.ipcStub.withArgs('searchCacheDaemon'),
stubTypes.length,
);
stubTypes.forEach((type, i) => {
// Assert that the stub was called with the resource we're trying to mock
// so we don't mistakenly mock the wrong resource
const call = this.searchCacheDaemonStub.getCall(i);
const ipcCall = this.ipcStub.withArgs('searchCacheDaemon').getCall(i);
let resource = type;
if (typeOf(type) === 'object') {
resource = type.resource;
}
const mappedResourceName = resourceNames[singularize(resource)];
sinon.assert.match(call.args[0], { resource: mappedResourceName });
sinon.assert.match(ipcCall.args[1], { resource: mappedResourceName });
});
sinon.restore();
@@ -1,34 +0,0 @@
/**
* Copyright IBM Corp. 2021, 2026
* SPDX-License-Identifier: BUSL-1.1
*/
import { settled } from '@ember/test-helpers';
export function createSetupMirage(startMirage) {
return function setupMirage(hooks) {
hooks.beforeEach(function () {
if (!this.owner) {
throw new Error(
'Must call one of the ember-qunit setupTest() / setupRenderingTest() / setupApplicationTest() first',
);
}
// the environment property here is configuration to the mirage server:
// https://github.com/miragejs/miragejs/blob/7ff4f3f6fe56bf0cb1648f5af3f5210fcb07e20b/types/index.d.ts#L383
// It is not related to ember's build environment. In this case for mirage the "test" environment does
// not load the default scenario:
// https://github.com/miragejs/miragejs/blob/7ff4f3f6fe56bf0cb1648f5af3f5210fcb07e20b/lib/server.js#L302
this.server = startMirage({ environment: 'test' });
});
hooks.afterEach(function () {
return settled().then(() => {
if (this.server) {
this.server.shutdown();
delete this.server;
}
});
});
};
}
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+3 -3
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -16,7 +16,7 @@ class InvalidRolePrincipalTypeError extends Error {
export default class RoleAbility extends ModelAbility {
// =services
@service abilities;
@service can;
// =permissions
@@ -64,6 +64,6 @@ export default class RoleAbility extends ModelAbility {
`Expected a role principal of type 'user', 'group', or 'managed-group'. Got '${type}'.`,
);
}
return this.abilities.can(`read ${type}`, this.model);
return this.can.can(`read ${type}`, this.model);
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+5 -37
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -131,34 +131,11 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
// which indicates that there are more items in the list
// or the batch size has not been reached
do {
try {
result = await super.query(store, schema, queryObject);
} catch (e) {
// If we hit a rate limit mid-pagination, return whatever
// data has been accumulated so far rather than throwing and leaving
// the user stuck with nothing to show.
// Without a list_token this is the very first request with nothing to
// show, so rethrow and let normal error handling apply.
if (e?.errors?.[0]?.isRateLimited && queryObject.list_token) {
result ??= {};
result.items = data;
result.response_type = 'complete';
result.meta = {
...result.meta,
rateLimitWarning: { retryAfter: e.errors[0].retryAfter },
};
return prenormalizeArrayResponse(result);
}
// For all other errors (or a 429 on the very first request with
// no data yet), rethrow so normal error handling applies.
throw e;
}
// Add the result items to a data array
result = await super.query(store, schema, queryObject);
//add the result items to a data array
if (result && result.items) {
data.push(...result.items);
// Pass in the list token for subsequent calls to fetch the remaining list items
//pass in the list token for subsequent calls to fetch the remaining list items
queryObject.list_token = result.list_token;
}
} while (
@@ -260,7 +237,6 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
* - `403 isForbidden`: the session is authenticated but does not have
* permission to perform the requested action
* - `404 isNotFound`: the requested resource could not be found
* - `429 isRateLimited`: the client has exceeded the rate limit
* - `500 isServer`: an internal server error occurred
* - `isUnknown`: an error occurred, but we don't know which or
* we don't distinguish it yet
@@ -272,7 +248,7 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
* @param {Object} payload
* @return {Array} errors payload
*/
normalizeErrorResponse(status, headers /*, payload*/) {
normalizeErrorResponse(/*status, headers, payload*/) {
const errors = super.normalizeErrorResponse(...arguments);
if (isArray(errors)) {
errors.forEach((error) => {
@@ -286,14 +262,6 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
case 404:
error.isNotFound = true;
break;
case 429:
error.isRateLimited = true;
// Attach rate-limit metadata from response headers so downstream
// error handlers can inform the user when they may retry.
error.retryAfter = Number(
headers['Retry-After'] ?? headers['retry-after'],
);
break;
case 500:
error.isServer = true;
break;
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -23,7 +23,7 @@ export default class HostCatalogAdapter extends ApplicationAdapter {
try {
const pluginName = snapshot.attr('plugin')?.name;
if (pluginName) url = `${url}?plugin_name=${pluginName}`;
} catch {
} catch (e) {
// Ignore any adapter errors here
}
}
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -23,7 +23,7 @@ export default class SessionRecordingAdapter extends ApplicationAdapter {
let method;
try {
method = snapshot?.adapterOptions?.method;
} catch {
} catch (e) {
// Ignore any adapter errors here
}
if (method === 'download') {
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -22,7 +22,7 @@ export default class StorageBucketAdapter extends ApplicationAdapter {
let pluginName;
try {
pluginName = snapshot?.attr('plugin')?.name;
} catch {
} catch (e) {
// Ignore any adapter errors here
}
if (requestType === 'createRecord' && pluginName) {
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -72,7 +72,7 @@ export default class GeneratedHostCatalogModel extends BaseModel {
@attr('string', {
for: {
type: 'plugin',
name: ['aws', 'azure', 'gcp'],
name: ['aws', 'gcp'],
},
description:
'An expression used to filter the workers that have network access to a service that is hosting the external object store.',
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -96,34 +96,6 @@ export default class GeneratedSessionRecordingModel extends BaseModel {
})
duration;
@attr({
description:
'The detailed state of the session recording. This contains storage_state, syncing_error_details, and verification_error_details.',
readOnly: true,
})
recording_state;
@attr('string', {
description:
'The availability of the session recording. One of "available" or "not available".',
readOnly: true,
})
availability;
@attr('date', {
description: 'The time until a session recording is required to be stored.',
readOnly: true,
})
retain_until;
@attr('date', {
description:
'The time a session recording is scheduled to be automatically deleted.',
readOnly: true,
})
delete_after;
// Deprecated: These two fields should be removed once support for RDP is added.
@attr('string', {
description:
'The current state of the session recording. One of "started", "available" and "unknown".',
@@ -137,4 +109,17 @@ export default class GeneratedSessionRecordingModel extends BaseModel {
readOnly: true,
})
error_details;
@attr('date', {
description: 'The time until a session recording is required to be stored.',
readOnly: true,
})
retain_until;
@attr('date', {
description:
'The time a session recording is scheduled to be automatically deleted.',
readOnly: true,
})
delete_after;
}
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -59,6 +59,7 @@ const fetchControllerData = async (context, next) => {
*/
export default class CacheDaemonHandler {
@service session;
@service ipc;
constructor(context) {
setOwner(this, getOwner(context));
@@ -69,8 +70,9 @@ export default class CacheDaemonHandler {
case 'query': {
const { store, data } = context.request;
const { type, query, options: { pushToStore = true } = {} } = data;
const isCacheDaemonRunning =
await window.desktop.daemon.isCacheDaemonRunning();
const isCacheDaemonRunning = await this.ipc.invoke(
'isCacheDaemonRunning',
);
// eslint-disable-next-line no-unused-vars
let { recursive, scope_id, page, pageSize, ...remainingQuery } = query;
@@ -99,14 +101,6 @@ export default class CacheDaemonHandler {
const token = sessionData?.token;
const resourceName = resourceNames[type];
if (remainingQuery.query?.sort) {
const { attribute, direction } = remainingQuery.query.sort;
if (attribute && direction) {
remainingQuery.sort_by = attribute;
remainingQuery.sort_direction = direction;
}
}
remainingQuery = {
...remainingQuery,
query: searchQuery,
@@ -117,19 +111,23 @@ export default class CacheDaemonHandler {
let cacheDaemonResults = {};
try {
cacheDaemonResults =
await window.desktop.daemon.searchCacheDaemon(remainingQuery);
cacheDaemonResults = await this.ipc.invoke(
'searchCacheDaemon',
remainingQuery,
);
} catch (e) {
// If we got a 403, most likely the cache daemon was restarted and our token is no longer valid
// I'm not sure if we can get a 401 since we always send a token but we'll handle it in the same way
if (e.statusCode === 403 || e.statusCode === 401) {
try {
await window.desktop.daemon.addTokenToDaemons({
await this.ipc.invoke('addTokenToDaemons', {
tokenId: auth_token_id,
token,
});
cacheDaemonResults =
await window.desktop.daemon.searchCacheDaemon(remainingQuery);
cacheDaemonResults = await this.ipc.invoke(
'searchCacheDaemon',
remainingQuery,
);
} catch (err) {
// If it fails again just fall back to fetching controller data
__electronLog?.error(
+10 -44
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -59,39 +59,17 @@ export default class SqliteHandler {
let payload,
listToken,
writeToDbPromise,
totalInsert = 0,
rateLimitWarning;
totalInsert = 0;
if (!peekDb) {
let tokenKey = `${type}-${hashCode(remainingQuery)}`;
// The global token key represents a recursive query from global scope,
// which pulls back every resource of this type.
const globalTokenKey = `${type}-${hashCode({ scope_id: 'global', recursive: true })}`;
const tokenKey = `${type}-${hashCode(remainingQuery)}`;
if (storeToken) {
// Always prefer the global token when it exists for
// any more fine-grained query. The global query already fetched every
// item for this resource type, so we should just re-use it.
if (tokenKey !== globalTokenKey) {
const [globalTokenObj] = await this.sqlite.fetchResource({
...generateSQLExpressions('token', {
filters: { id: [{ equals: globalTokenKey }] },
}),
});
if (globalTokenObj?.token) {
tokenKey = globalTokenKey;
listToken = globalTokenObj.token;
}
}
// Only look up the specific token if no global token was found.
if (!listToken) {
const [tokenObj] = await this.sqlite.fetchResource({
...generateSQLExpressions('token', {
filters: { id: [{ equals: tokenKey }] },
}),
});
listToken = tokenObj?.token;
}
const [tokenObj] = await this.sqlite.fetchResource({
...generateSQLExpressions('token', {
filters: { id: [{ equals: tokenKey }] },
}),
});
listToken = tokenObj?.token;
} else {
// This is a temporary fix of clearing the DB (specifically for auth-methods)
// since we are not storing the token we do not get back a list of removed_ids
@@ -108,11 +86,6 @@ export default class SqliteHandler {
});
totalInsert += payload.items?.length ?? 0;
// Propagate any rate-limit warning the adapter attached
if (payload.meta?.rateLimitWarning) {
rateLimitWarning = payload.meta.rateLimitWarning;
}
// await the previous writeToDbPromise before writing to db again
if (writeToDbPromise) {
await writeToDbPromise;
@@ -190,14 +163,7 @@ export default class SqliteHandler {
// This isn't conventional but is better than returning an ArrayProxy
// or EmberArray since the ember store query method asserts it has to be an array
// so we can't just return an object.
records.meta = {
totalItems: count[0].total,
};
if (rateLimitWarning) {
records.meta.rateLimitWarning = rateLimitWarning;
}
records.meta = { totalItems: count[0].total };
return records;
}
default:
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2026
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
Loaded 100 of 2311 files, more files were not shown because too many files have changed in this diff. Show more