Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e63f6bd0f | ||
|
|
01e50cb8ce | ||
|
|
1a97b8b428 | ||
|
|
3f2be6fab0 | ||
|
|
89089dbb9a | ||
|
|
25d78b2fc5 | ||
|
|
4565676d4b | ||
|
|
ed9371fab7 | ||
|
|
68a01cfa3a | ||
|
|
b7129e38a8 | ||
|
|
26e27fd24b | ||
|
|
d0612c0a46 | ||
|
|
347107c109 | ||
|
|
0dac4ccf47 | ||
|
|
b8ea558f14 | ||
|
|
4fc061ec48 | ||
|
|
3313cd5316 | ||
|
|
af36d75252 | ||
|
|
72a69fbe8d | ||
|
|
e77ed3ae53 | ||
|
|
677a3c925b | ||
|
|
4cbe08276a | ||
|
|
20699d62dc | ||
|
|
048339982e | ||
|
|
2709c2e081 | ||
|
|
5e3addcc41 | ||
|
|
576fef9f8a | ||
|
|
b9517e0233 | ||
|
|
4d7ce40469 | ||
|
|
fa51973e6d | ||
|
|
f80d7ebeb3 | ||
|
|
9aea1a8fd8 | ||
|
|
35377e8466 | ||
|
|
0e580e3c9f | ||
|
|
e38d3afa58 | ||
|
|
0e223ded8f | ||
|
|
4e2b779d96 | ||
|
|
71ec7b465a | ||
|
|
8b870556a6 | ||
|
|
ecefa39b98 | ||
|
|
4a206c82dc | ||
|
|
2d0ed53202 | ||
|
|
5000d98e23 | ||
|
|
4afd7c2d0b | ||
|
|
207b1e8a7c | ||
|
|
8b90db1ff5 | ||
|
|
7fc10855d9 | ||
|
|
7c3be7c9a0 | ||
|
|
7cddf7cb91 | ||
|
|
878bd241f3 | ||
|
|
4aec0d3acc | ||
|
|
e43625f76c | ||
|
|
5b51edd17f | ||
|
|
6eb21d3e13 | ||
|
|
9b43819865 | ||
|
|
562b371db3 | ||
|
|
89d492042e | ||
|
|
f9197d5a99 | ||
|
|
ebd7f64fe3 | ||
|
|
7dadc53fe1 | ||
|
|
3d257afd49 | ||
|
|
95918cb997 | ||
|
|
077200d792 | ||
|
|
f34a1df298 | ||
|
|
7fa59bfd5d | ||
|
|
e0b80b1176 | ||
|
|
0479c3c8fc | ||
|
|
08b8b03fed | ||
|
|
1a8c895ea9 | ||
|
|
990146fa34 | ||
|
|
e5657a8d4c | ||
|
|
1d126dc074 | ||
|
|
dc224268f5 | ||
|
|
4c15d72321 | ||
|
|
add2a9d6c4 | ||
|
|
759c1f5555 | ||
|
|
37de7e3480 | ||
|
|
d469f305de | ||
|
|
fd1eba617b | ||
|
|
5048fd478a | ||
|
|
de907284ff | ||
|
|
6e9fe1c675 | ||
|
|
6b29a875f3 | ||
|
|
1fd638618b | ||
|
|
6704a251e0 | ||
|
|
46ed965360 | ||
|
|
283e128139 | ||
|
|
047db02a65 | ||
|
|
bd837a6383 | ||
|
|
2a6fac66fc | ||
|
|
4bdcd4ce69 | ||
|
|
9f76650dfb | ||
|
|
c33d1718a2 | ||
|
|
923dedc9bb | ||
|
|
2d9b9d9659 | ||
|
|
6d7e24fdc5 | ||
|
|
4f9086642b | ||
|
|
337963bff8 | ||
|
|
b87ed9f3db | ||
|
|
95b78299f9 | ||
|
|
cf0df900e0 | ||
|
|
214304dc8c | ||
|
|
ed8075d200 | ||
|
|
07089e97e2 | ||
|
|
14b3c8c6d0 | ||
|
|
6580350dcf | ||
|
|
51be681758 | ||
|
|
dab50e352d | ||
|
|
f3af41dea4 | ||
|
|
fb3f88a77d | ||
|
|
7345c79b20 | ||
|
|
9ed79be3ef | ||
|
|
7614f17efb | ||
|
|
ec698d5672 | ||
|
|
266f10d1eb | ||
|
|
e30168c55a | ||
|
|
4e7d6ba57e | ||
|
|
f3968d353d | ||
|
|
33055d6095 | ||
|
|
f48e6dc049 | ||
|
|
605b7940e3 | ||
|
|
7454ecf57a | ||
|
|
28b185bec8 | ||
|
|
e345946c7d | ||
|
|
6c3a57b599 | ||
|
|
52e36e6463 | ||
|
|
392e49bf49 | ||
|
|
eba17d3c71 | ||
|
|
cdfeee3916 | ||
|
|
f59603d70a | ||
|
|
638dbff235 | ||
|
|
e310b5abfa | ||
|
|
b63ea6eee0 | ||
|
|
780740f2f2 | ||
|
|
163758a1cb | ||
|
|
e91bf99f6d | ||
|
|
43c9389b69 | ||
|
|
79b6360c30 | ||
|
|
93d709f7ba | ||
|
|
999c21c66a | ||
|
|
d6e8e58ca1 | ||
|
|
df24ba6a15 | ||
|
|
b1b49edb39 | ||
|
|
aaabfbe54d | ||
|
|
51ee5b2b20 | ||
|
|
566a02cbeb | ||
|
|
3a847605ed | ||
|
|
772857dbad | ||
|
|
9e069ffc0c | ||
|
|
ba77e9dd1b | ||
|
|
ea1e7a99de | ||
|
|
46ededd676 | ||
|
|
b2b42cafd4 | ||
|
|
b6154cb1f7 | ||
|
|
ebe5ae5f19 | ||
|
|
f8af37db43 | ||
|
|
4de3b5a61f | ||
|
|
3829301c24 | ||
|
|
e68e17c5d4 | ||
|
|
63b810d53f | ||
|
|
72fa6d86c4 | ||
|
|
1780077068 | ||
|
|
1e49283a33 | ||
|
|
6f7138be46 | ||
|
|
709d6e0be8 | ||
|
|
3ba93927fe | ||
|
|
733c4c546c | ||
|
|
99713ea0e1 | ||
|
|
b493285ee1 | ||
|
|
3e88411998 | ||
|
|
55e1e68f30 | ||
|
|
055da3d958 | ||
|
|
bd9b094834 | ||
|
|
773c1596e5 | ||
|
|
1d0941865b | ||
|
|
ecdf9c5b42 | ||
|
|
89f94a9d07 | ||
|
|
0b7e3fcad1 | ||
|
|
4170c7aa24 | ||
|
|
c8737f0474 | ||
|
|
43249169d8 | ||
|
|
ab2c235c52 | ||
|
|
d45548e612 | ||
|
|
f1ffb80b80 | ||
|
|
9204c63b17 | ||
|
|
b5d33948dc | ||
|
|
29fb5b00cb | ||
|
|
f3a124cc47 | ||
|
|
2766be2c2e | ||
|
|
b9d064c949 | ||
|
|
0bac7d2711 | ||
|
|
1d08ddb513 | ||
|
|
824427b690 | ||
|
|
183bde311c | ||
|
|
30c2cab0b7 | ||
|
|
6fcc743217 |
No files matched your search
+1
-2
@@ -2,13 +2,12 @@ schema_version = 1
|
|||||||
|
|
||||||
project {
|
project {
|
||||||
license = "BUSL-1.1"
|
license = "BUSL-1.1"
|
||||||
copyright_year = 2024
|
copyright_year = 2021
|
||||||
|
|
||||||
# (OPTIONAL) A list of globs that should not have copyright/license headers.
|
# (OPTIONAL) A list of globs that should not have copyright/license headers.
|
||||||
# Supports doublestar glob patterns for more flexibility in defining which
|
# Supports doublestar glob patterns for more flexibility in defining which
|
||||||
# files or folders should be ignored
|
# files or folders should be ignored
|
||||||
header_ignore = [
|
header_ignore = [
|
||||||
".github/**",
|
|
||||||
".husky/**",
|
".husky/**",
|
||||||
"**/node_modules/**",
|
"**/node_modules/**",
|
||||||
"**/dist/**",
|
"**/dist/**",
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
tags-ignore: ["**"]
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "41 5 * * *" # nightly: dependency audit + full test run
|
||||||
|
|
||||||
|
# One job on purpose: the shared runner pool is small, so everything runs
|
||||||
|
# sequentially on a single runner instead of a matrix.
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 90
|
||||||
|
env:
|
||||||
|
CI: "true"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "22"
|
||||||
|
|
||||||
|
- name: install pnpm
|
||||||
|
run: |
|
||||||
|
npm install -g pnpm@10.33.3
|
||||||
|
pnpm --version
|
||||||
|
|
||||||
|
- name: install dependencies
|
||||||
|
# Lifecycle scripts are skipped: the desktop postinstall compiles
|
||||||
|
# electron-app native modules, which the admin build and ember tests
|
||||||
|
# do not need.
|
||||||
|
run: pnpm install --frozen-lockfile --ignore-scripts
|
||||||
|
|
||||||
|
- name: install headless chrome
|
||||||
|
# Debian/Ubuntu chromium from the distro archive (fast, mirrored),
|
||||||
|
# exposed under the name testem's "Chrome" launcher looks for.
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if ! command -v google-chrome >/dev/null 2>&1; then
|
||||||
|
SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo"
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
$SUDO apt-get update -qq
|
||||||
|
$SUDO apt-get install -y -qq --no-install-recommends chromium \
|
||||||
|
|| $SUDO apt-get install -y -qq --no-install-recommends chromium-browser
|
||||||
|
CHROME_BIN=$(command -v chromium || command -v chromium-browser)
|
||||||
|
mkdir -p "$HOME/bin"
|
||||||
|
ln -sf "$CHROME_BIN" "$HOME/bin/google-chrome"
|
||||||
|
echo "$HOME/bin" >> "$GITHUB_PATH"
|
||||||
|
fi
|
||||||
|
PATH="$HOME/bin:$PATH" google-chrome --version
|
||||||
|
|
||||||
|
- name: build admin ui
|
||||||
|
run: pnpm --filter admin build
|
||||||
|
|
||||||
|
- name: test addons
|
||||||
|
run: |
|
||||||
|
for a in core auth rose; do
|
||||||
|
echo "::group::addons/$a"
|
||||||
|
(cd addons/$a && npx ember test --test-port 0)
|
||||||
|
echo "::endgroup::"
|
||||||
|
done
|
||||||
|
echo "::group::addons/api"
|
||||||
|
(cd addons/api && npx ember exam --test-port 0 --split=4 --parallel=1)
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: test desktop ui
|
||||||
|
run: cd ui/desktop && npx ember test --test-port 0
|
||||||
|
|
||||||
|
- name: test admin ui
|
||||||
|
# The test build is made once and the partitions then run against the
|
||||||
|
# static output, one browser at a time. Rebuilding in-process (and four
|
||||||
|
# concurrent browsers) stalled on the small shared runners.
|
||||||
|
run: |
|
||||||
|
cd ui/admin
|
||||||
|
npx ember build --environment=test --output-path="$RUNNER_TEMP/admin-test-dist"
|
||||||
|
for p in 1 2 3 4; do
|
||||||
|
echo "::group::admin partition $p/4"
|
||||||
|
timeout 25m npx ember exam --test-port 0 --path "$RUNNER_TEMP/admin-test-dist" --split=4 --partition=$p
|
||||||
|
echo "::endgroup::"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: dependency audit
|
||||||
|
# Fails on critical advisories only; remaining high/moderate advisories
|
||||||
|
# are build/test tooling and are tracked in pnpm-overrides.md.
|
||||||
|
run: |
|
||||||
|
pnpm audit --audit-level=critical
|
||||||
|
(cd ui/desktop/electron-app && pnpm audit --audit-level=critical)
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Anyone attached to this rule will always been assigned to a pull request
|
|
||||||
* @hashicorp/boundary-ui
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Let us know about a bug!
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- Please reserve GitHub issues for bug reports and feature requests.
|
|
||||||
|
|
||||||
For questions, the best place to get answers is on our [discussion forum](https://discuss.hashicorp.com/c/boundary), as they will get more visibility from experienced users than the issue tracker.
|
|
||||||
|
|
||||||
Please note: We take Boundary's security and our users' trust very seriously. If you believe you have found a security issue in Boundary, please responsibly disclose this by contacting us at security@hashicorp.com. Our PGP key is available on [our security page](https://www.hashicorp.com/security/).
|
|
||||||
|
|
||||||
Logging is available on Boundary Desktop Client version >= 2.1.0
|
|
||||||
|
|
||||||
Logs are found at:
|
|
||||||
|
|
||||||
Linux: ~/.config/Boundary/logs/desktop-client.log
|
|
||||||
MacOS: ~/Library/Logs/Boundary/desktop-client.log
|
|
||||||
Windows: $env:USERPROFILE\AppData\Roaming\Boundary\logs\desktop-client.log
|
|
||||||
|
|
||||||
If requests are taking longer than expected, please change the logging level to DEBUG. This will log the cache daemon request times as well.
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
## :bug: Bug Report
|
|
||||||
|
|
||||||
### **Description**
|
|
||||||
|
|
||||||
_A clear and concise description of the bug._
|
|
||||||
|
|
||||||
### **Steps to Reproduce**
|
|
||||||
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '...'
|
|
||||||
3. Scroll down to '...'
|
|
||||||
4. See the error
|
|
||||||
|
|
||||||
## **Expected behavior**
|
|
||||||
|
|
||||||
_A clear description of what you expected to happen._
|
|
||||||
|
|
||||||
## **Actual behavior**
|
|
||||||
|
|
||||||
_A clear description of what actually happened._
|
|
||||||
|
|
||||||
## **Screenshots (if applicable)**
|
|
||||||
|
|
||||||
_Add screenshots or screen recordings to help explain the issue._
|
|
||||||
|
|
||||||
## **Environment**
|
|
||||||
|
|
||||||
- **OS and Version:** (e.g., Windows 10 (22H2), macOS (14.7.2))
|
|
||||||
- **Architecture:** (e.g., arm64, x86_64)
|
|
||||||
- **Browser/Version:** (if applicable)
|
|
||||||
- **Desktop Client Version:** (if applicable)
|
|
||||||
- **Controller/worker versions:** (if applicable)
|
|
||||||
|
|
||||||
## **Logs & Console Output (if applicable)**
|
|
||||||
|
|
||||||
_Paste any relevant error logs or browser console output here._
|
|
||||||
|
|
||||||
## **Additional Context**
|
|
||||||
|
|
||||||
_Any other details that might be relevant._
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# Copyright (c) HashiCorp, Inc.
|
|
||||||
# SPDX-License-Identifier: BUSL-1.1
|
|
||||||
|
|
||||||
contact_links:
|
|
||||||
- name: Ask a question
|
|
||||||
url: https://discuss.hashicorp.com/c/boundary
|
|
||||||
about: For increased visibility, please post questions on the discussion forum.
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest something!
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Explain any additional use-cases**
|
|
||||||
If there are any use-cases that would help us understand the use/need/value please share them as they can help us decide on acceptance and prioritization.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "monthly"
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Copyright (c) HashiCorp, Inc.
|
|
||||||
# SPDX-License-Identifier: BUSL-1.1
|
|
||||||
|
|
||||||
addons:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "addons/**/*"
|
|
||||||
|
|
||||||
api-addon:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "addons/api/**/*"
|
|
||||||
|
|
||||||
auth-addon:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "addons/auth/**/*"
|
|
||||||
|
|
||||||
styles-addon:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "addons/rose/**/*"
|
|
||||||
|
|
||||||
ui:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "ui/**/*"
|
|
||||||
|
|
||||||
admin:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "ui/admin/**/*"
|
|
||||||
|
|
||||||
desktop:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "ui/desktop/**/*"
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Description
|
|
||||||
<!-- Add a brief description of changes here -->
|
|
||||||
|
|
||||||
<!-- Uncomment line below to manually add link to JIRA ticket -->
|
|
||||||
<!-- :tickets: [Jira ticket](https://hashicorp.atlassian.net/browse/JIRA_TICKET_NUMBER) -->
|
|
||||||
|
|
||||||
## Screenshots (if appropriate)
|
|
||||||
|
|
||||||
## How to Test
|
|
||||||
<!-- Add steps to test this change. Include any other necessary relevant links -->
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
<!-- strikethrough the checklist item that is not relevant to your change -->
|
|
||||||
|
|
||||||
<!-- If you are merging a long lived branch, major feature, or UI altering changes,
|
|
||||||
please add the a11y-tests label. Other cases, like a dependency change or
|
|
||||||
translation update likely does not need an a11y audit -->
|
|
||||||
|
|
||||||
- [ ] I have added before and after screenshots for UI changes
|
|
||||||
- [ ] I have added JSON response output for API changes
|
|
||||||
- [ ] I have added steps to reproduce and test for bug fixes in the description
|
|
||||||
- [ ] I have commented on my code, particularly in hard-to-understand areas
|
|
||||||
- [ ] My changes generate no new warnings
|
|
||||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
|
||||||
- [ ] I have added `a11y-tests` label to run a11y audit tests if needed
|
|
||||||
|
|
||||||
## PCI review checklist
|
|
||||||
|
|
||||||
<!-- heimdall_github_prtemplate:grc-pci_dss-2024-01-05 -->
|
|
||||||
- [ ] I have documented a clear reason for, and description of, the change I am making.
|
|
||||||
- [ ] If applicable, I've documented a plan to revert these changes if they require more than reverting the pull request.
|
|
||||||
- [ ] If applicable, I've documented the impact of any changes to security controls.
|
|
||||||
Examples of changes to security controls include using new access control methods, adding or removing logging pipelines, etc.
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) HashiCorp, Inc.
|
|
||||||
# SPDX-License-Identifier: BUSL-1.1
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Configure Git
|
|
||||||
git config --global user.email "hc-github-team-secure-boundary@hashicorp.com"
|
|
||||||
git config --global user.name "github-team-secure-boundary"
|
|
||||||
# Fetch branches from ENT
|
|
||||||
git fetch origin
|
|
||||||
BRANCH=${1}
|
|
||||||
|
|
||||||
echo "BRANCH to merge is $BRANCH"
|
|
||||||
git checkout "${BRANCH}"
|
|
||||||
|
|
||||||
# Checkout OSS repo
|
|
||||||
git remote add oss-remote https://github.com/hashicorp/boundary-ui.git
|
|
||||||
git fetch oss-remote
|
|
||||||
|
|
||||||
# Merge oss/${BRANCH} into ent/${BRANCH}
|
|
||||||
git_merge_branch="${2}"
|
|
||||||
git checkout -b "${git_merge_branch}"
|
|
||||||
latest_oss_commit="$(git rev-parse --short oss-remote/${BRANCH})"
|
|
||||||
echo "Trying to merge the latest oss commit - ${latest_oss_commit} from oss/${BRANCH} into ent/${BRANCH}"
|
|
||||||
|
|
||||||
if ! errors=$(git merge -m "Merge Boundary UI OSS branch '${BRANCH}' at commit ${latest_oss_commit}" "${latest_oss_commit}"); then
|
|
||||||
# Here we can try to auto resolve conflicts
|
|
||||||
# This logic will vary from project to project. The below is just an example.
|
|
||||||
conflicts=$(git diff --name-only --diff-filter=U)
|
|
||||||
printf "Found conflicts:\n${conflicts}\n"
|
|
||||||
# Resolve package.json conflicts by taking oss
|
|
||||||
if echo "$conflicts" | grep -q package.json; then
|
|
||||||
echo "Checking out oss package.json..."
|
|
||||||
git checkout --theirs package.json
|
|
||||||
git add package.json
|
|
||||||
fi
|
|
||||||
# Resolve pnpm-lock.yaml conflicts by re-running pnpm install:
|
|
||||||
# https://pnpm.io/git#merge-conflicts
|
|
||||||
if echo "$conflicts" | grep -q pnpm-lock.yaml; then
|
|
||||||
echo "Re-running pnpm install to fix conflicts by regenerating pnpm-lock.yaml..."
|
|
||||||
pnpm install
|
|
||||||
git add pnpm-lock.yaml
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If we can commit all the changes without conflict, we have resolved everything automatically
|
|
||||||
if ! git commit --no-edit; then
|
|
||||||
echo "Auto Merge failed, creating a draft PR"
|
|
||||||
git merge --abort
|
|
||||||
git clean -xfd
|
|
||||||
git fetch oss-remote
|
|
||||||
git checkout "${OSS_BRANCH}"
|
|
||||||
git checkout -b "${OSS_LOCAL_BRANCH}"
|
|
||||||
git push -f --set-upstream origin "${OSS_LOCAL_BRANCH}"
|
|
||||||
gh pr create \
|
|
||||||
--draft \
|
|
||||||
--fill-first \
|
|
||||||
--label "oss-merge" \
|
|
||||||
-B "${BASE_BRANCH}" \
|
|
||||||
-H "${OSS_LOCAL_BRANCH}" \
|
|
||||||
-a "${ACTOR}" \
|
|
||||||
-t "[${BASE_BRANCH/oss\/release\//}] OSS to ENT merge of (${SHA::7})" \
|
|
||||||
-b "${BASE_BRANCH/oss\//} upstream merge of (${SHA::7})
|
|
||||||
Merge failed, Please fix the conflicts using github UI or using the following commands:
|
|
||||||
\`\`\`bash
|
|
||||||
git checkout ${BASE_BRANCH}
|
|
||||||
git pull
|
|
||||||
git checkout ${OSS_LOCAL_BRANCH}
|
|
||||||
git merge ${BASE_BRANCH}
|
|
||||||
# fix conflicts and commit
|
|
||||||
git push origin ${OSS_LOCAL_BRANCH}
|
|
||||||
\`\`\`"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check that there are actually changes to merge by comparing the
|
|
||||||
# merge branch to the current checked out branch
|
|
||||||
if (git diff ${BRANCH} --exit-code > /dev/null); then
|
|
||||||
echo "there are no changes to merge"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
git push origin "${git_merge_branch}"
|
|
||||||
gh pr create \
|
|
||||||
--fill-first \
|
|
||||||
--label "oss-merge" \
|
|
||||||
-B "${BASE_BRANCH}" \
|
|
||||||
-H "${MERGE_BRANCH}" \
|
|
||||||
-a ${ACTOR} \
|
|
||||||
-t "[${BASE_BRANCH/oss\/release\//}] OSS to ENT merge of (${SHA::7})" \
|
|
||||||
-b "${BASE_BRANCH/oss\//} upstream merge of (${SHA::7})"
|
|
||||||
gh pr merge --auto --merge
|
|
||||||
|
|
||||||
# This PR will be need to be approved manually
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
name: A11y Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [labeled, opened, synchronize, reopened]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
a11y-test:
|
|
||||||
name: Run A11y Tests
|
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'a11y-tests')
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
timeout-minutes: 40
|
|
||||||
steps:
|
|
||||||
- uses: browser-actions/setup-chrome@b94431e051d1c52dcbe9a7092a4f10f827795416 # v2.1.0
|
|
||||||
with:
|
|
||||||
install-dependencies: true
|
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
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:
|
|
||||||
# this will generate the test reports but causes tests to pass even when there a11y failures
|
|
||||||
ENABLE_A11Y_MIDDLEWARE_REPORTER: true
|
|
||||||
run: pnpm test-a11y
|
|
||||||
- name: Consolidate ember a11y reports
|
|
||||||
run: |
|
|
||||||
mkdir ember-a11y-reports
|
|
||||||
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? })}) })"'
|
|
||||||
- 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? })}) })"'
|
|
||||||
- name: Upload ember a11y reports
|
|
||||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
|
||||||
with:
|
|
||||||
name: ember-a11y-reports
|
|
||||||
path: ./ember-a11y-reports
|
|
||||||
- name: Report a11y test results status
|
|
||||||
if: always()
|
|
||||||
# fail CI when the combined array length of admin and desktop a11y reports is not 0
|
|
||||||
run: |
|
|
||||||
EMBER_A11Y_FAILURE_COUNT=$(jq -s 'map(.[]) | length' ember-a11y-reports/admin.json ember-a11y-reports/desktop.json)
|
|
||||||
echo "$EMBER_A11Y_FAILURE_COUNT ember-a11y test failures"
|
|
||||||
if [ "$EMBER_A11Y_FAILURE_COUNT" != '0' ]; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
name: Build Admin UI
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- "release/**"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
dependencies:
|
|
||||||
name: Install dependencies
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
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@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
- 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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
|
||||||
with:
|
|
||||||
name: admin-ui
|
|
||||||
path: ./ui/admin/dist/
|
|
||||||
- name: Upload artifact OSS admin UI
|
|
||||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
|
||||||
with:
|
|
||||||
name: admin-ui-oss
|
|
||||||
path: ./ui/admin/dist/
|
|
||||||
build-admin-ui-enterprise:
|
|
||||||
name: Build Admin UI Enterprise
|
|
||||||
needs: [dependencies]
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
- 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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
|
||||||
with:
|
|
||||||
name: admin-ui-ent
|
|
||||||
path: ./ui/admin/dist/
|
|
||||||
build-admin-ui-hcp:
|
|
||||||
name: Build Admin UI HCP
|
|
||||||
needs: [dependencies]
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
run_install: false
|
|
||||||
- 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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
|
||||||
with:
|
|
||||||
name: admin-ui-hcp
|
|
||||||
path: ./ui/admin/dist/
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
# For most projects, this workflow file will not need changing; you simply need
|
|
||||||
# to commit it to your repository.
|
|
||||||
#
|
|
||||||
# You may wish to alter this file to override the set of languages analyzed,
|
|
||||||
# or to provide custom queries or build logic.
|
|
||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [main]
|
|
||||||
schedule:
|
|
||||||
- cron: '0 19 * * 4'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# Override automatic language detection by changing the below list
|
|
||||||
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
|
|
||||||
language: ['javascript']
|
|
||||||
# Learn more...
|
|
||||||
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@70df9def86d22bf0ea4e7f8b956e7b92e7c1ea22 # codeql-bundle-v2.20.7
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
||||||
# By default, queries listed here will override any specified in a config file.
|
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
||||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
|
||||||
# 📚 https://git.io/JvXDl
|
|
||||||
|
|
||||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
|
||||||
# and modify them (or add more) to build your code if your project
|
|
||||||
# uses a compiled language
|
|
||||||
|
|
||||||
#- run: |
|
|
||||||
# make bootstrap
|
|
||||||
# make release
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@70df9def86d22bf0ea4e7f8b956e7b92e7c1ea22 # codeql-bundle-v2.20.7
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
name: Add Copyright Headers
|
|
||||||
on: pull_request
|
|
||||||
jobs:
|
|
||||||
copywrite:
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- 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 }}
|
|
||||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
|
||||||
- uses: hashicorp/setup-copywrite@32638da2d4e81d56a0764aa1547882fc4d209636 # v1.1.3
|
|
||||||
- name: Add missing Copyright Headers
|
|
||||||
run: copywrite headers
|
|
||||||
- uses: stefanzweifel/git-auto-commit-action@28e16e81777b558cc906c8750092100bbb34c5e3 # v7.0.0
|
|
||||||
with:
|
|
||||||
commit_message: Add missing copyright headers
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
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,11 +0,0 @@
|
|||||||
name: "Pull Request Labeler"
|
|
||||||
on:
|
|
||||||
- pull_request_target
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
triage:
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
|
|
||||||
with:
|
|
||||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
name: Validate Monorepo
|
|
||||||
on: pull_request
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
name: Install dependencies
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
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:
|
|
||||||
name: License Compliance
|
|
||||||
needs: [dependencies]
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
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 --offline
|
|
||||||
- run: pnpm run compliance:licenses
|
|
||||||
|
|
||||||
lint:
|
|
||||||
name: Lint
|
|
||||||
needs: [dependencies, compliance]
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
timeout-minutes: 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
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 --offline
|
|
||||||
- run: pnpm lint
|
|
||||||
|
|
||||||
test:
|
|
||||||
name: Test
|
|
||||||
needs: [lint]
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
timeout-minutes: 15
|
|
||||||
steps:
|
|
||||||
- uses: browser-actions/setup-chrome@b94431e051d1c52dcbe9a7092a4f10f827795416 # v2.1.0
|
|
||||||
with:
|
|
||||||
install-dependencies: true
|
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
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 --offline
|
|
||||||
- run: pnpm test
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
name: Trigger OSS to Enterprise Merge
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types:
|
|
||||||
- closed
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
trigger-oss-merge:
|
|
||||||
# Run this only on merge events in OSS repo
|
|
||||||
if: ${{ github.event.pull_request.merged && github.repository == 'hashicorp/boundary-ui' }}
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
steps:
|
|
||||||
- name: Trigger Merge
|
|
||||||
env:
|
|
||||||
GIT_REF: ${{ github.ref_name }}
|
|
||||||
GIT_SHA: ${{ github.sha }}
|
|
||||||
GH_PAT: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
|
|
||||||
GIT_ACTOR: ${{ github.actor }}
|
|
||||||
run: |
|
|
||||||
curl -H "Authorization: token $GH_PAT" \
|
|
||||||
-H 'Accept: application/json' \
|
|
||||||
-d "{\"event_type\": \"oss-merge\", \"client_payload\": {\"git-ref\": \"${GIT_REF}\", \"git-sha\": \"${GIT_SHA}\", \"git-actor\": \"${GIT_ACTOR}\" }}" \
|
|
||||||
"https://api.github.com/repos/hashicorp/boundary-ui-enterprise/dispatches"
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
name: OSS → ENT Merge
|
|
||||||
on:
|
|
||||||
repository_dispatch:
|
|
||||||
types: [ oss-merge ]
|
|
||||||
jobs:
|
|
||||||
oss-merge:
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
|
|
||||||
- run: |
|
|
||||||
git fetch --prune --unshallow
|
|
||||||
./.github/scripts/merge.sh "${BASE_BRANCH}" "${MERGE_BRANCH}"
|
|
||||||
env:
|
|
||||||
BASE_BRANCH: ${{ github.event.client_payload.git-ref }}
|
|
||||||
OSS_BRANCH: oss-remote/${{ github.event.client_payload.git-ref }}
|
|
||||||
OSS_LOCAL_BRANCH: oss/${{ github.event.client_payload.git-ref }}-${{ github.event.client_payload.git-sha }}
|
|
||||||
MERGE_BRANCH: oss/merge-${{ github.event.client_payload.git-ref }}-${{github.event.client_payload.git-sha}}
|
|
||||||
GITHUB_TOKEN: ${{secrets.ELEVATED_GITHUB_TOKEN }}
|
|
||||||
MERGE_APPROVE_TOKEN: ${{secrets.ELEVATED_GITHUB_TOKEN }}
|
|
||||||
ACTOR: ${{ github.event.client_payload.git-actor }}
|
|
||||||
SHA: ${{github.event.client_payload.git-sha}}
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
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:
|
|
||||||
description: 'Branch of boundary-enterprise to test against (default to main)'
|
|
||||||
required: true
|
|
||||||
default: 'main'
|
|
||||||
type: string
|
|
||||||
boundary-branch:
|
|
||||||
description: 'Branch of boundary to test against (default to main)'
|
|
||||||
required: true
|
|
||||||
default: 'main'
|
|
||||||
type: string
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
name: test
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER_UBUNTU_22) }}
|
|
||||||
strategy:
|
|
||||||
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@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Set up pnpm
|
|
||||||
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
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@b9cd54a3c349d3f38e8881555d616ced269862dd
|
|
||||||
|
|
||||||
- name: Set up Enos
|
|
||||||
uses: hashicorp/action-setup-enos@39a8f388434bea5eeba6649b99aa9949a55a1150
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install Vault CLI
|
|
||||||
run: |
|
|
||||||
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: |
|
|
||||||
# Create a GPG key
|
|
||||||
export KEY_PW=boundary
|
|
||||||
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
|
|
||||||
export lines=$(gpg --list-secret-keys --with-colons --with-keygrip)
|
|
||||||
export 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
|
|
||||||
export 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
|
|
||||||
pass init $KEY_ID &>/dev/null
|
|
||||||
|
|
||||||
- name: Checkout ${{ matrix.folder_name }} repo
|
|
||||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
with:
|
|
||||||
repository: ${{ matrix.github_repo }}
|
|
||||||
path: support/src/${{ matrix.folder_name }}
|
|
||||||
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
|
|
||||||
ref: ${{ matrix.boundary_branch }}
|
|
||||||
|
|
||||||
- name: GH fix for localhost resolution
|
|
||||||
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
|
|
||||||
|
|
||||||
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 node dependencies
|
|
||||||
run: |
|
|
||||||
pnpm install --frozen-lockfile
|
|
||||||
cd e2e-tests
|
|
||||||
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
|
|
||||||
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 && \
|
|
||||||
export ENOS_VAR_boundary_license="${{ secrets.BOUNDARY_ENT_LICENSE }}" && \
|
|
||||||
enos scenario launch --timeout 60m0s --chdir ./support/src/${{matrix.folder_name}}/enos ${{matrix.enos_scenario}} builder:local
|
|
||||||
|
|
||||||
- name: Move boundary binary
|
|
||||||
run: |
|
|
||||||
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 }} --reporter=html
|
|
||||||
|
|
||||||
- name: Upload Playwright report
|
|
||||||
if: ${{ failure() }}
|
|
||||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
|
||||||
with:
|
|
||||||
name: playwright-report-${{ matrix.boundary_edition }}
|
|
||||||
path: e2e-tests/playwright-report
|
|
||||||
|
|
||||||
- name: Clean up test infra
|
|
||||||
if: ${{ always() }}
|
|
||||||
run: |
|
|
||||||
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 && \
|
|
||||||
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@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 failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Branch:* ${{ github.repository }}:${{ github.head_ref }}"
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
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:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
name: test
|
|
||||||
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@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Set up pnpm
|
|
||||||
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 #v4.2.0
|
|
||||||
with:
|
|
||||||
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@b9cd54a3c349d3f38e8881555d616ced269862dd
|
|
||||||
|
|
||||||
- name: Set up Enos
|
|
||||||
uses: hashicorp/action-setup-enos@39a8f388434bea5eeba6649b99aa9949a55a1150
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install Vault CLI
|
|
||||||
run: |
|
|
||||||
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: Checkout boundary-enterprise
|
|
||||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
with:
|
|
||||||
repository: hashicorp/boundary-enterprise
|
|
||||||
# ref: ${{ github.event.inputs.boundary-enterprise-branch }}
|
|
||||||
path: support/src/boundary-enterprise
|
|
||||||
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: GH fix for localhost resolution
|
|
||||||
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
|
|
||||||
|
|
||||||
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: |
|
|
||||||
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_enos_user=$GITHUB_ACTOR && \
|
|
||||||
export ENOS_VAR_aws_ssh_private_key_path=~/.ssh/github_enos && \
|
|
||||||
export ENOS_VAR_boundary_license="${{ secrets.BOUNDARY_ENT_LICENSE }}" && \
|
|
||||||
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
|
|
||||||
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
|
|
||||||
sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 &
|
|
||||||
pnpm run desktop
|
|
||||||
|
|
||||||
- name: Upload Playwright report
|
|
||||||
if: ${{ failure() }}
|
|
||||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
|
||||||
with:
|
|
||||||
name: playwright-report
|
|
||||||
path: e2e-tests/playwright-report
|
|
||||||
|
|
||||||
- name: Clean up test infra
|
|
||||||
if: ${{ always() }}
|
|
||||||
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:crt
|
|
||||||
|
|
||||||
- name: Send Slack message on failure
|
|
||||||
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 }}"
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
name: "Trigger Boundary Desktop release"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
trigger-gha-release:
|
|
||||||
runs-on: ${{ fromJSON(vars.RUNNER) }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
||||||
- name: Release description
|
|
||||||
run: |
|
|
||||||
echo "Triggering release with a TAG ${GITHUB_REF#refs/tags/}"
|
|
||||||
- name: Trigger Release workflow in boundary-desktop-releases
|
|
||||||
run: |
|
|
||||||
export GITHUB_TOKEN="${{ secrets.ELEVATED_GITHUB_TOKEN }}"
|
|
||||||
gh workflow run release.yml \
|
|
||||||
--repo hashicorp/boundary-desktop-releases \
|
|
||||||
--ref main \
|
|
||||||
-f TAG="${GITHUB_REF#refs/tags/}"
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
# Copyright (c) HashiCorp, Inc.
|
|
||||||
# SPDX-License-Identifier: BUSL-1.1
|
|
||||||
|
|
||||||
url_license = "https://github.com/hashicorp/boundary-ui/blob/main/LICENSE"
|
|
||||||
url_project_website = "https://learn.hashicorp.com/tutorials/boundary/getting-started-desktop-app"
|
|
||||||
url_source_repository = "https://github.com/hashicorp/boundary-ui"
|
|
||||||
@@ -3,21 +3,21 @@ License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.
|
|||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
|
||||||
Licensor: HashiCorp, Inc.
|
Licensor: International Business Machines Corporation (IBM)
|
||||||
Licensed Work: The Licensed Work is (c) 2024 HashiCorp, Inc.
|
Licensed Work: The Licensed Work is (c) 2024 IBM Corp.
|
||||||
Additional Use Grant: You may make production use of the Licensed Work, provided
|
Additional Use Grant: You may make production use of the Licensed Work, provided
|
||||||
Your use does not include offering the Licensed Work to third
|
Your use does not include offering the Licensed Work to third
|
||||||
parties on a hosted or embedded basis in order to compete with
|
parties on a hosted or embedded basis in order to compete with
|
||||||
HashiCorp's paid version(s) of the Licensed Work. For purposes
|
IBM Corp's paid version(s) of the Licensed Work. For purposes
|
||||||
of this license:
|
of this license:
|
||||||
|
|
||||||
A "competitive offering" is a Product that is offered to third
|
A "competitive offering" is a Product that is offered to third
|
||||||
parties on a paid basis, including through paid support
|
parties on a paid basis, including through paid support
|
||||||
arrangements, that significantly overlaps with the capabilities
|
arrangements, that significantly overlaps with the capabilities
|
||||||
of HashiCorp's paid version(s) of the Licensed Work. If Your
|
of IBM Corp's paid version(s) of the Licensed Work. If Your
|
||||||
Product is not a competitive offering when You first make it
|
Product is not a competitive offering when You first make it
|
||||||
generally available, it will not become a competitive offering
|
generally available, it will not become a competitive offering
|
||||||
later due to HashiCorp releasing a new version of the Licensed
|
later due to IBM Corp releasing a new version of the Licensed
|
||||||
Work with additional capabilities. In addition, Products that
|
Work with additional capabilities. In addition, Products that
|
||||||
are not provided on a paid basis are not competitive.
|
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
|
Hosting or using the Licensed Work(s) for internal purposes
|
||||||
within an organization is not considered a competitive
|
within an organization is not considered a competitive
|
||||||
offering. HashiCorp considers your organization to include all
|
offering. IBM Corp considers your organization to include all
|
||||||
of your affiliates under common control.
|
of your affiliates under common control.
|
||||||
|
|
||||||
For binding interpretive guidance on using HashiCorp products
|
For binding interpretive guidance on using IBM Corp products
|
||||||
under the Business Source License, please visit our FAQ.
|
under the Business Source License, please visit our FAQ.
|
||||||
(https://www.hashicorp.com/license-faq)
|
(https://www.hashicorp.com/license-faq)
|
||||||
Change Date: Four years from the date the Licensed Work is published.
|
Change Date: Four years from the date the Licensed Work is published.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
Threshold UI
|
||||||
|
Copyright (c) 2026 CyberCove LLC
|
||||||
|
|
||||||
|
This repository is a community fork of "Boundary UI"
|
||||||
|
(https://github.com/hashicorp/boundary-ui), the admin web UI and desktop
|
||||||
|
client for HashiCorp Boundary.
|
||||||
|
|
||||||
|
Upstream work: Copyright (c) HashiCorp, Inc. 2020-2023;
|
||||||
|
Copyright (c) IBM Corp. 2024-2026
|
||||||
|
Upstream license: Business Source License 1.1 (see LICENSE)
|
||||||
|
|
||||||
|
The upstream LICENSE and per-file copyright / SPDX headers are retained
|
||||||
|
unchanged. Modifications made in this fork are provided under the same
|
||||||
|
license terms (BUSL-1.1), including its Additional Use Grant and Change
|
||||||
|
Date as stated in LICENSE.
|
||||||
|
|
||||||
|
This project is an independent community effort. It is NOT affiliated with,
|
||||||
|
endorsed by, or sponsored by HashiCorp, Inc. or IBM Corp. "HashiCorp",
|
||||||
|
"Boundary", and related marks and logos are trademarks of their respective
|
||||||
|
owners; they are used here only to describe the upstream origin of this work
|
||||||
|
and to name the upstream CLI/API this software interoperates with. The
|
||||||
|
upstream logos and brand art have been removed and replaced with plain
|
||||||
|
placeholder marks.
|
||||||
|
|
||||||
|
Third-party components keep their own licenses (see pnpm-lock.yaml and the
|
||||||
|
`pnpm compliance:licenses` script). The HashiCorp Design System packages
|
||||||
|
(@hashicorp/design-system-components, -tokens, @hashicorp/flight-icons) are
|
||||||
|
consumed unmodified from the public npm registry under their own licenses.
|
||||||
@@ -1,10 +1,41 @@
|
|||||||
# Boundary UI Monorepo
|
# Threshold UI Monorepo
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
This monorepo contains multiple projects, including UIs and addons, used by
|
This monorepo contains multiple projects, including UIs and addons, used by
|
||||||
Boundary.
|
Threshold (the admin web UI and the desktop client).
|
||||||
|
|
||||||
|
## About this fork
|
||||||
|
|
||||||
|
This repository is a community fork of
|
||||||
|
[hashicorp/boundary-ui](https://github.com/hashicorp/boundary-ui), rebranded
|
||||||
|
for the Threshold project (a community fork of Boundary CE). It is licensed
|
||||||
|
under the upstream Business Source License 1.1 (see [LICENSE](LICENSE) and
|
||||||
|
[NOTICE](NOTICE)) and is **not affiliated with, endorsed by, or sponsored by
|
||||||
|
HashiCorp or IBM**.
|
||||||
|
|
||||||
|
What changed relative to upstream:
|
||||||
|
|
||||||
|
- User-visible product name is Threshold (window titles, menus, about dialog,
|
||||||
|
installer/package names, app id `net.anhonesthost.cybercove.threshold`).
|
||||||
|
API paths, field names, protocol strings and environment variable names are
|
||||||
|
unchanged for compatibility with the server. The desktop client's persisted
|
||||||
|
settings are copied from the former "Boundary" user-data directory on first
|
||||||
|
launch.
|
||||||
|
- The desktop client looks for a `threshold` CLI first, then `boundary`.
|
||||||
|
- HashiCorp/IBM logos and brand art were removed and replaced with plain
|
||||||
|
placeholder marks.
|
||||||
|
- Nothing contacts HashiCorp services by default. The in-app updater, the
|
||||||
|
"unsupported controller" release-metadata lookup, and the CLI bundling
|
||||||
|
download are disabled until you configure your own hosts:
|
||||||
|
`THRESHOLD_UPDATE_FEED_URL` (desktop build, updater feed),
|
||||||
|
`THRESHOLD_RELEASES_METADATA_URL` / `THRESHOLD_RELEASES_PAGE_URL`
|
||||||
|
(desktop build, release links) and `THRESHOLD_CLI_RELEASES_URL` /
|
||||||
|
`THRESHOLD_CLI_ARCHIVE_PREFIX` (used with `SETUP_CLI=true` to bundle a CLI).
|
||||||
|
- Documentation links still point at the upstream Boundary documentation,
|
||||||
|
which is user-initiated only.
|
||||||
|
- Upstream HashiCorp-internal GitHub workflows and release metadata were
|
||||||
|
removed; CI lives in `.gitea/workflows/ci.yml`.
|
||||||
|
|
||||||
|
Upstream history, CHANGELOGs and copyright headers are preserved.
|
||||||
|
|
||||||
This top-level repository provides limited common tasks, such as installation
|
This top-level repository provides limited common tasks, such as installation
|
||||||
and commit assistance. However, most tasks must be executed from within a
|
and commit assistance. However, most tasks must be executed from within a
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
# unconventional js
|
|
||||||
/blueprints/*/files/
|
|
||||||
|
|
||||||
# compiled output
|
|
||||||
/declarations/
|
|
||||||
/dist/
|
|
||||||
|
|
||||||
# misc
|
|
||||||
/coverage/
|
|
||||||
!.*
|
|
||||||
.*/
|
|
||||||
|
|
||||||
# ember-try
|
|
||||||
/.node_modules.ember-try/
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+38
-5
@@ -21,17 +21,50 @@ This addon contains the API data access layer for Boundary.
|
|||||||
## Add API to an App
|
## Add API to an App
|
||||||
|
|
||||||
Add this addon to an Ember application's `devDependencies` as:
|
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.
|
||||||
|
|
||||||
Since this addon also includes Mirage mocks, be sure to install
|
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`
|
||||||
`ember-cli-mirage` and add the following config to your UI project:
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
'ember-cli-mirage': {
|
mirage: {
|
||||||
directory: '../../addons/api/mirage'
|
enabled: true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
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
|
## Installation
|
||||||
|
|
||||||
See monorepo README for installation instructions.
|
See monorepo README for installation instructions.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* 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.
|
* This test helper can be used to help setup your sinon stubs in your tests.
|
||||||
* Must be called after setupMirage.
|
* Must be called after setupMirage and setupDesktopContextBridgeApiMock in tests.
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* import setupStubs from 'api/test-support/handlers/cache-daemon-search';
|
* import setupStubs from 'api/test-support/handlers/cache-daemon-search';
|
||||||
@@ -19,14 +19,15 @@ import { underscore } from '@ember/string';
|
|||||||
* module('Acceptance | my test', function(hooks) {
|
* module('Acceptance | my test', function(hooks) {
|
||||||
* setupApplicationTest(hooks);
|
* setupApplicationTest(hooks);
|
||||||
* setupMirage(hooks);
|
* setupMirage(hooks);
|
||||||
|
* setupDesktopContextBridgeApiMock(hooks);
|
||||||
* setupStubs(hooks);
|
* setupStubs(hooks);
|
||||||
*
|
*
|
||||||
* // add your actual tests here
|
* // add your actual tests here
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This will setup a stub for the IPC service and include helper methods to
|
* This will setup a stub for window.desktop.daemon.searchCacheDaemon and include
|
||||||
* help setup what the cache daemon search command returns.
|
* helper methods to help setup what the cache daemon search command returns.
|
||||||
*
|
*
|
||||||
* @module Test Helpers
|
* @module Test Helpers
|
||||||
* @public
|
* @public
|
||||||
@@ -35,9 +36,6 @@ export default function setupStubs(hooks) {
|
|||||||
let stubTypes = [];
|
let stubTypes = [];
|
||||||
|
|
||||||
hooks.beforeEach(function () {
|
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
|
* 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
|
* search. However, the handler expects the search data to be raw JSON from
|
||||||
@@ -56,34 +54,32 @@ export default function setupStubs(hooks) {
|
|||||||
stubTypes = types;
|
stubTypes = types;
|
||||||
|
|
||||||
types.forEach((type, i) => {
|
types.forEach((type, i) => {
|
||||||
this.ipcStub
|
this.searchCacheDaemonStub.onCall(i).callsFake(() => {
|
||||||
.withArgs('searchCacheDaemon')
|
let models;
|
||||||
.onCall(i)
|
let resourceName;
|
||||||
.callsFake(() => {
|
if (typeOf(type) === 'object') {
|
||||||
let models;
|
models = type.func();
|
||||||
let resourceName;
|
resourceName = type.resource;
|
||||||
if (typeOf(type) === 'object') {
|
} else {
|
||||||
models = type.func();
|
models = this.server.schema[type].all().models;
|
||||||
resourceName = type.resource;
|
resourceName = type;
|
||||||
} else {
|
}
|
||||||
models = this.server.schema[type].all().models;
|
|
||||||
resourceName = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[underscore(resourceNames[singularize(resourceName)])]:
|
[underscore(resourceNames[singularize(resourceName)])]: models.map(
|
||||||
models.map((model) => {
|
(model) => {
|
||||||
// Use internal serializer to serialize the model correctly
|
// Use internal serializer to serialize the model correctly
|
||||||
// according to our mirage serializers
|
// according to our mirage serializers
|
||||||
const modelData =
|
const modelData =
|
||||||
this.server.serializerOrRegistry.serialize(model);
|
this.server.serializerOrRegistry.serialize(model);
|
||||||
|
|
||||||
// Serialize the data properly to standard JSON as that is what
|
// Serialize the data properly to standard JSON as that is what
|
||||||
// we're expecting from the cache daemon response
|
// we're expecting from the cache daemon response
|
||||||
return JSON.parse(JSON.stringify(modelData));
|
return JSON.parse(JSON.stringify(modelData));
|
||||||
}),
|
},
|
||||||
};
|
),
|
||||||
});
|
};
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -91,22 +87,19 @@ export default function setupStubs(hooks) {
|
|||||||
hooks.afterEach(function () {
|
hooks.afterEach(function () {
|
||||||
// Verify the number of mocks we set up match with how
|
// Verify the number of mocks we set up match with how
|
||||||
// many times the cache daemon was called with
|
// many times the cache daemon was called with
|
||||||
sinon.assert.callCount(
|
sinon.assert.callCount(this.searchCacheDaemonStub, stubTypes.length);
|
||||||
this.ipcStub.withArgs('searchCacheDaemon'),
|
|
||||||
stubTypes.length,
|
|
||||||
);
|
|
||||||
|
|
||||||
stubTypes.forEach((type, i) => {
|
stubTypes.forEach((type, i) => {
|
||||||
// Assert that the stub was called with the resource we're trying to mock
|
// Assert that the stub was called with the resource we're trying to mock
|
||||||
// so we don't mistakenly mock the wrong resource
|
// so we don't mistakenly mock the wrong resource
|
||||||
const ipcCall = this.ipcStub.withArgs('searchCacheDaemon').getCall(i);
|
const call = this.searchCacheDaemonStub.getCall(i);
|
||||||
let resource = type;
|
let resource = type;
|
||||||
if (typeOf(type) === 'object') {
|
if (typeOf(type) === 'object') {
|
||||||
resource = type.resource;
|
resource = type.resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mappedResourceName = resourceNames[singularize(resource)];
|
const mappedResourceName = resourceNames[singularize(resource)];
|
||||||
sinon.assert.match(ipcCall.args[1], { resource: mappedResourceName });
|
sinon.assert.match(call.args[0], { resource: mappedResourceName });
|
||||||
});
|
});
|
||||||
|
|
||||||
sinon.restore();
|
sinon.restore();
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* 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 (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ class InvalidRolePrincipalTypeError extends Error {
|
|||||||
export default class RoleAbility extends ModelAbility {
|
export default class RoleAbility extends ModelAbility {
|
||||||
// =services
|
// =services
|
||||||
|
|
||||||
@service can;
|
@service abilities;
|
||||||
|
|
||||||
// =permissions
|
// =permissions
|
||||||
|
|
||||||
@@ -64,6 +64,6 @@ export default class RoleAbility extends ModelAbility {
|
|||||||
`Expected a role principal of type 'user', 'group', or 'managed-group'. Got '${type}'.`,
|
`Expected a role principal of type 'user', 'group', or 'managed-group'. Got '${type}'.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return this.can.can(`read ${type}`, this.model);
|
return this.abilities.can(`read ${type}`, this.model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -131,11 +131,34 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
|
|||||||
// which indicates that there are more items in the list
|
// which indicates that there are more items in the list
|
||||||
// or the batch size has not been reached
|
// or the batch size has not been reached
|
||||||
do {
|
do {
|
||||||
result = await super.query(store, schema, queryObject);
|
try {
|
||||||
//add the result items to a data array
|
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
|
||||||
if (result && result.items) {
|
if (result && result.items) {
|
||||||
data.push(...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;
|
queryObject.list_token = result.list_token;
|
||||||
}
|
}
|
||||||
} while (
|
} while (
|
||||||
@@ -237,6 +260,7 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
|
|||||||
* - `403 isForbidden`: the session is authenticated but does not have
|
* - `403 isForbidden`: the session is authenticated but does not have
|
||||||
* permission to perform the requested action
|
* permission to perform the requested action
|
||||||
* - `404 isNotFound`: the requested resource could not be found
|
* - `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
|
* - `500 isServer`: an internal server error occurred
|
||||||
* - `isUnknown`: an error occurred, but we don't know which or
|
* - `isUnknown`: an error occurred, but we don't know which or
|
||||||
* we don't distinguish it yet
|
* we don't distinguish it yet
|
||||||
@@ -248,7 +272,7 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
|
|||||||
* @param {Object} payload
|
* @param {Object} payload
|
||||||
* @return {Array} errors payload
|
* @return {Array} errors payload
|
||||||
*/
|
*/
|
||||||
normalizeErrorResponse(/*status, headers, payload*/) {
|
normalizeErrorResponse(status, headers /*, payload*/) {
|
||||||
const errors = super.normalizeErrorResponse(...arguments);
|
const errors = super.normalizeErrorResponse(...arguments);
|
||||||
if (isArray(errors)) {
|
if (isArray(errors)) {
|
||||||
errors.forEach((error) => {
|
errors.forEach((error) => {
|
||||||
@@ -262,6 +286,14 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
|
|||||||
case 404:
|
case 404:
|
||||||
error.isNotFound = true;
|
error.isNotFound = true;
|
||||||
break;
|
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:
|
case 500:
|
||||||
error.isServer = true;
|
error.isServer = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ export default class HostCatalogAdapter extends ApplicationAdapter {
|
|||||||
try {
|
try {
|
||||||
const pluginName = snapshot.attr('plugin')?.name;
|
const pluginName = snapshot.attr('plugin')?.name;
|
||||||
if (pluginName) url = `${url}?plugin_name=${pluginName}`;
|
if (pluginName) url = `${url}?plugin_name=${pluginName}`;
|
||||||
} catch (e) {
|
} catch {
|
||||||
// Ignore any adapter errors here
|
// Ignore any adapter errors here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ export default class SessionRecordingAdapter extends ApplicationAdapter {
|
|||||||
let method;
|
let method;
|
||||||
try {
|
try {
|
||||||
method = snapshot?.adapterOptions?.method;
|
method = snapshot?.adapterOptions?.method;
|
||||||
} catch (e) {
|
} catch {
|
||||||
// Ignore any adapter errors here
|
// Ignore any adapter errors here
|
||||||
}
|
}
|
||||||
if (method === 'download') {
|
if (method === 'download') {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ export default class StorageBucketAdapter extends ApplicationAdapter {
|
|||||||
let pluginName;
|
let pluginName;
|
||||||
try {
|
try {
|
||||||
pluginName = snapshot?.attr('plugin')?.name;
|
pluginName = snapshot?.attr('plugin')?.name;
|
||||||
} catch (e) {
|
} catch {
|
||||||
// Ignore any adapter errors here
|
// Ignore any adapter errors here
|
||||||
}
|
}
|
||||||
if (requestType === 'createRecord' && pluginName) {
|
if (requestType === 'createRecord' && pluginName) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ export default class GeneratedHostCatalogModel extends BaseModel {
|
|||||||
@attr('string', {
|
@attr('string', {
|
||||||
for: {
|
for: {
|
||||||
type: 'plugin',
|
type: 'plugin',
|
||||||
name: ['aws', 'gcp'],
|
name: ['aws', 'azure', 'gcp'],
|
||||||
},
|
},
|
||||||
description:
|
description:
|
||||||
'An expression used to filter the workers that have network access to a service that is hosting the external object store.',
|
'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 (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -96,19 +96,19 @@ export default class GeneratedSessionRecordingModel extends BaseModel {
|
|||||||
})
|
})
|
||||||
duration;
|
duration;
|
||||||
|
|
||||||
@attr('string', {
|
@attr({
|
||||||
description:
|
description:
|
||||||
'The current state of the session recording. One of "started", "available" and "unknown".',
|
'The detailed state of the session recording. This contains storage_state, syncing_error_details, and verification_error_details.',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
})
|
})
|
||||||
state;
|
recording_state;
|
||||||
|
|
||||||
@attr('string', {
|
@attr('string', {
|
||||||
description:
|
description:
|
||||||
'Any error seen during the closing of the session recording. Currently only set if state is "unknown".',
|
'The availability of the session recording. One of "available" or "not available".',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
})
|
})
|
||||||
error_details;
|
availability;
|
||||||
|
|
||||||
@attr('date', {
|
@attr('date', {
|
||||||
description: 'The time until a session recording is required to be stored.',
|
description: 'The time until a session recording is required to be stored.',
|
||||||
@@ -122,4 +122,19 @@ export default class GeneratedSessionRecordingModel extends BaseModel {
|
|||||||
readOnly: true,
|
readOnly: true,
|
||||||
})
|
})
|
||||||
delete_after;
|
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".',
|
||||||
|
readOnly: true,
|
||||||
|
})
|
||||||
|
state;
|
||||||
|
|
||||||
|
@attr('string', {
|
||||||
|
description:
|
||||||
|
'Any error seen during the closing of the session recording. Currently only set if state is "unknown".',
|
||||||
|
readOnly: true,
|
||||||
|
})
|
||||||
|
error_details;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -59,7 +59,6 @@ const fetchControllerData = async (context, next) => {
|
|||||||
*/
|
*/
|
||||||
export default class CacheDaemonHandler {
|
export default class CacheDaemonHandler {
|
||||||
@service session;
|
@service session;
|
||||||
@service ipc;
|
|
||||||
|
|
||||||
constructor(context) {
|
constructor(context) {
|
||||||
setOwner(this, getOwner(context));
|
setOwner(this, getOwner(context));
|
||||||
@@ -70,9 +69,8 @@ export default class CacheDaemonHandler {
|
|||||||
case 'query': {
|
case 'query': {
|
||||||
const { store, data } = context.request;
|
const { store, data } = context.request;
|
||||||
const { type, query, options: { pushToStore = true } = {} } = data;
|
const { type, query, options: { pushToStore = true } = {} } = data;
|
||||||
const isCacheDaemonRunning = await this.ipc.invoke(
|
const isCacheDaemonRunning =
|
||||||
'isCacheDaemonRunning',
|
await window.desktop.daemon.isCacheDaemonRunning();
|
||||||
);
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
let { recursive, scope_id, page, pageSize, ...remainingQuery } = query;
|
let { recursive, scope_id, page, pageSize, ...remainingQuery } = query;
|
||||||
@@ -101,6 +99,14 @@ export default class CacheDaemonHandler {
|
|||||||
const token = sessionData?.token;
|
const token = sessionData?.token;
|
||||||
const resourceName = resourceNames[type];
|
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 = {
|
||||||
...remainingQuery,
|
...remainingQuery,
|
||||||
query: searchQuery,
|
query: searchQuery,
|
||||||
@@ -111,23 +117,19 @@ export default class CacheDaemonHandler {
|
|||||||
|
|
||||||
let cacheDaemonResults = {};
|
let cacheDaemonResults = {};
|
||||||
try {
|
try {
|
||||||
cacheDaemonResults = await this.ipc.invoke(
|
cacheDaemonResults =
|
||||||
'searchCacheDaemon',
|
await window.desktop.daemon.searchCacheDaemon(remainingQuery);
|
||||||
remainingQuery,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// If we got a 403, most likely the cache daemon was restarted and our token is no longer valid
|
// 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
|
// 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) {
|
if (e.statusCode === 403 || e.statusCode === 401) {
|
||||||
try {
|
try {
|
||||||
await this.ipc.invoke('addTokenToDaemons', {
|
await window.desktop.daemon.addTokenToDaemons({
|
||||||
tokenId: auth_token_id,
|
tokenId: auth_token_id,
|
||||||
token,
|
token,
|
||||||
});
|
});
|
||||||
cacheDaemonResults = await this.ipc.invoke(
|
cacheDaemonResults =
|
||||||
'searchCacheDaemon',
|
await window.desktop.daemon.searchCacheDaemon(remainingQuery);
|
||||||
remainingQuery,
|
|
||||||
);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// If it fails again just fall back to fetching controller data
|
// If it fails again just fall back to fetching controller data
|
||||||
__electronLog?.error(
|
__electronLog?.error(
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -59,17 +59,39 @@ export default class SqliteHandler {
|
|||||||
let payload,
|
let payload,
|
||||||
listToken,
|
listToken,
|
||||||
writeToDbPromise,
|
writeToDbPromise,
|
||||||
totalInsert = 0;
|
totalInsert = 0,
|
||||||
|
rateLimitWarning;
|
||||||
|
|
||||||
if (!peekDb) {
|
if (!peekDb) {
|
||||||
const tokenKey = `${type}-${hashCode(remainingQuery)}`;
|
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 })}`;
|
||||||
if (storeToken) {
|
if (storeToken) {
|
||||||
const [tokenObj] = await this.sqlite.fetchResource({
|
// Always prefer the global token when it exists for
|
||||||
...generateSQLExpressions('token', {
|
// any more fine-grained query. The global query already fetched every
|
||||||
filters: { id: [{ equals: tokenKey }] },
|
// item for this resource type, so we should just re-use it.
|
||||||
}),
|
if (tokenKey !== globalTokenKey) {
|
||||||
});
|
const [globalTokenObj] = await this.sqlite.fetchResource({
|
||||||
listToken = tokenObj?.token;
|
...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;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a temporary fix of clearing the DB (specifically for auth-methods)
|
// 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
|
// since we are not storing the token we do not get back a list of removed_ids
|
||||||
@@ -86,6 +108,11 @@ export default class SqliteHandler {
|
|||||||
});
|
});
|
||||||
totalInsert += payload.items?.length ?? 0;
|
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
|
// await the previous writeToDbPromise before writing to db again
|
||||||
if (writeToDbPromise) {
|
if (writeToDbPromise) {
|
||||||
await writeToDbPromise;
|
await writeToDbPromise;
|
||||||
@@ -163,7 +190,14 @@ export default class SqliteHandler {
|
|||||||
// This isn't conventional but is better than returning an ArrayProxy
|
// 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
|
// or EmberArray since the ember store query method asserts it has to be an array
|
||||||
// so we can't just return an object.
|
// so we can't just return an object.
|
||||||
records.meta = { totalItems: count[0].total };
|
records.meta = {
|
||||||
|
totalItems: count[0].total,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (rateLimitWarning) {
|
||||||
|
records.meta.rateLimitWarning = rateLimitWarning;
|
||||||
|
}
|
||||||
|
|
||||||
return records;
|
return records;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright IBM Corp. 2021, 2026
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
Loaded 100 of 2336 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user