Skip to content

Commit

Permalink
standalone: add unfurl init test, use /-/overview for blueprint pages
Browse files Browse the repository at this point in the history
  • Loading branch information
AjBreidenbach committed Jul 5, 2024
1 parent c51f982 commit 648c5d6
Show file tree
Hide file tree
Showing 19 changed files with 219 additions and 61 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/build_test_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 16
- name: git config
run: git config --global user.email "[email protected]"; git config --global user.name "Your Name"
- name: Install yarn dependencies
run: npm i -g yarn && YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install
# TODO add back ufsv-patch -- --runInBand
Expand All @@ -55,6 +57,12 @@ jobs:
run: yarn integration-test run --namespace onecommons/blueprints -- -e GENERATE_SUBDOMAINS=true --browser chrome -s cypress/e2e/blueprints/aws__baserow__baserow.cy.js
- name: pkill
run: pkill unfurl || /bin/true
- name: Integration test (unfurl init)
env:
STANDALONE_SETUP_SCRIPT: testing-shared/unfurl-init-setup.sh
run: yarn integration-test run --namespace onecommons/blueprints -- -e GENERATE_SUBDOMAINS=true --browser chrome -s cypress/e2e/blueprints/aws__minecraft__minecraft.cy.js
- name: pkill
run: pkill unfurl || /bin/true
- name: Integration test (staging upstream)
run: yarn integration-test run --namespace onecommons/blueprints -- -e GENERATE_SUBDOMAINS=true --browser chrome -s cypress/e2e/blueprints/aws__baserow__baserow.cy.js
env:
Expand Down
4 changes: 3 additions & 1 deletion cypress/support/create-aws-environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ Cypress.Commands.add('createAWSEnvironment', (options) => {

// create external resource
if (shouldCreateExternalResource) {
cy.whenInstancesAbsent(environmentName, () => {
cy.whenInstancesAbsent(environmentName, (env) => {
if(Object.keys(env.repositories).filter(repo => repo != '_dashboard').length == 0) return

viewingEnv || cy.visit(`/${DASHBOARD_DEST}/-/environments/${environmentName}`)
if(shouldCreateDNS) {
cy.uncheckedCreateDNS(AWS_DNS_TYPE, AWS_DNS_ZONE)
Expand Down
54 changes: 29 additions & 25 deletions cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const INTEGRATION_TEST_ARGS = Cypress.env('INTEGRATION_TEST_ARGS')
const UNFURL_SERVER_URL = Cypress.env('UNFURL_SERVER_URL')
const UNFURL_CLOUDMAP_PATH = Cypress.env('UNFURL_CLOUDMAP_PATH')
const UNFURL_PACKAGE_RULES = Cypress.env('UNFURL_PACKAGE_RULES')
const STANDALONE_UNFURL = Cypress.env('STANDALONE_UNFURL')

const UNFURL_VALIDATION_MODE = Cypress.env('UNFURL_VALIDATION_MODE') || Cypress.env('VALIDATION_MODE')

Expand Down Expand Up @@ -138,32 +139,35 @@ beforeEach(() => {
})
}

cy.document().then(doc => {
const csrf = doc.querySelector('meta[name="csrf-token"]')?.content

const win = doc.parentView || doc.defaultView

cy.request({
method: 'PATCH',
url: `/${DASHBOARD_DEST || win.gon.home_project}/-/variables`,
failOnStatusCode: false,
headers: {
'X-CSRF-Token': csrf
},
body: {
"variables_attributes": [
{
"key": "UNFURL_SKIP_SAVE",
"secret_value": "never",
"environment_scope": "*",
"variable_type": "env_var",
"masked": false,
"protected": false
}
]
}
// set via unfurl environment in standalone tests
if(!STANDALONE_UNFURL) {
cy.document().then(doc => {
const csrf = doc.querySelector('meta[name="csrf-token"]')?.content

const win = doc.parentView || doc.defaultView

cy.request({
method: 'PATCH',
url: `/${DASHBOARD_DEST || win.gon.home_project}/-/variables`,
failOnStatusCode: false,
headers: {
'X-CSRF-Token': csrf
},
body: {
"variables_attributes": [
{
"key": "UNFURL_SKIP_SAVE",
"secret_value": "never",
"environment_scope": "*",
"variable_type": "env_var",
"masked": false,
"protected": false
}
]
}
})
})
})
}

cy.window().then(win => {
if(DEPLOY_IMAGE) {
Expand Down
23 changes: 18 additions & 5 deletions cypress/support/environments.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ const

import slugify from '../../packages/oc-pages/vue_shared/slugify'

/**
* Custom Cypress command to wait until the environment is ready,
* then execute a callback with the environment and store as arguments.
*
* Note: Assertions can be directly chained on the return value of this command.
* This is because Cypress commands return Promises, allowing for assertions
* like `cy.withEnvironment('envName').should('exist')`. The callback function
* does not affect this behavior as long as the command returns the expected value.
*
* @param {string} environmentName - The name of the environment to look up.
* @param {Function} cb - A callback function that receives the environment and store.
* @returns {Cypress.Chainable} - Returns a chainable Cypress command.
*/
Cypress.Commands.add('withEnvironment', (environmentName, cb) => {
return cy.waitUntil(() => cy.withStore().then(store => {
if(!store.getters.environmentsAreReady) return false
Expand All @@ -30,25 +43,25 @@ Cypress.Commands.add('withEnvironment', (environmentName, cb) => {
}), {timeout: BASE_TIMEOUT * 2, interval: 500})
.then(store => {
const env = store.getters.lookupEnvironment(environmentName) || null
cb && cb(env)
cb && cb(env, store) // store in callback for convenience
return env
})
})

Cypress.Commands.add('whenEnvironmentExists', (environmentName, cb) => {
return cy.withEnvironment(environmentName).then(env => env && cb(env))
return cy.withEnvironment(environmentName).then((env, store) => env && cb(env, store))
})

Cypress.Commands.add('whenEnvironmentAbsent', (environmentName, cb) => {
return cy.withEnvironment(environmentName).then(env => !env && cb())
return cy.withEnvironment(environmentName).then((env, store) => !env && cb(store))
})

Cypress.Commands.add('whenInstancesAbsent', (environmentName, cb) => {
return cy.withEnvironment(environmentName).then( env => {
return cy.withEnvironment(environmentName).then((env, store) => {
if(! env) return
if(Object.values(env.instances || {})
.filter(instance => instance.name != 'dns-zone') == 0) {
cb()
cb(env, store)
}
})
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<script>
import * as routes from '../../router/constants'
import {withApplicationLinkTarget} from './mixins'
import ProjectIcon from 'oc_vue_shared/components/oc/project-icon.vue'
export default {
components: { ProjectIcon },
mixins: [withApplicationLinkTarget],
props: {
application: {
type: Object,
Expand All @@ -14,14 +16,23 @@ export default {
projectIconSrc: null,
}
},
computed: {
applicationLinkTarget() {
if(!this.application.projectPath) return null
if(window.gon.unfurl_gui) {
return `/${this.application.projectPath}/-/overview`
}
return `/${this.application.projectPath}`
}
},
async created() {
this.projectIconSrc = await this.application.projectIcon
}
}
</script>
<template>
<!-- TODO use router link when possible -->
<a :href="application.projectPath && application.projectPath != '.' ? `/${application.projectPath}`: null">
<a :href="applicationLinkTarget">
<div v-if="application" class="status-item font-weight-bold">
<project-icon :projectIcon="projectIconSrc" />
{{application.title}}
Expand Down
73 changes: 73 additions & 0 deletions packages/oc-pages/dashboard/components/cells/combined-cell.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<script>
import * as routes from '../../router/constants'
import DeploymentStatusIcon from './shared/deployment-status-icon.vue'
import {mapGetters} from 'vuex'
import _ from 'lodash'
import DashboardRouterLink from "../../components/dashboard-router-link.vue"
import {withApplicationLinkTarget} from './mixins'
export default {
components: { DeploymentStatusIcon, DashboardRouterLink },
mixins: [withApplicationLinkTarget],
props: {
deployment: {
type: Object,
required: true
},
environment: {
type: Object,
required: true
},
application: {
type: Object,
required: true
},
displayStatus: {
type: Boolean,
default: true
},
noRouter: {
type: Boolean,
default: false
},
scope: {
type: Object,
required: true
},
},
data() {
return {routes}
},
computed: {
...mapGetters(['deploymentItemDirect']),
deploymentItem() {
const {environment, deployment} = this
const deploymentItem = this.deploymentItemDirect({environment, deployment})
return deploymentItem
},
statuses() {
return _.uniqBy(this.deployment.statuses || [], 'type')
}
}
}
</script>
<template>
<div class="d-flex">
<deployment-status-icon :scope="scope" width="40px"/>
<div v-if="application" style="display: flex; flex-direction: column;" :class="{'hash-fragment': `#${deployment.name}` == $route.hash}">
<dashboard-router-link :noRouter="noRouter" :href="noRouter? deploymentItem.viewableLink: deploymentItem.viewableTo">
<b>{{deployment.title}}:</b>
</dashboard-router-link>
<a :href="applicationLinkTarget">
({{application.title}})
</a>

</div>
</div>
</template>
<style scoped>
.status-item {
display: flex;
align-items: center;
}
</style>
11 changes: 11 additions & 0 deletions packages/oc-pages/dashboard/components/cells/mixins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const withApplicationLinkTarget = {
computed: {
applicationLinkTarget() {
if(!this.application.projectPath) return null
if(window.gon.unfurl_gui) {
return `/${this.application.projectPath}/-/overview`
}
return `/${this.application.projectPath}`
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script>
import TableComponent from 'oc_vue_shared/components/oc/table.vue'
import {OcTab, EnvironmentSelection, LocalDeploy, AutostopInner} from 'oc_vue_shared/components/oc'
import CombinedCell from '../cells/combined-cell.vue'
import EnvironmentCell from '../cells/environment-cell.vue'
import ResourceCell from '../cells/resource-cell.vue'
import DeploymentControls from '../cells/deployment-controls.vue'
import DeploymentStatusIcon from '../cells/shared/deployment-status-icon.vue'
import LastDeploy from './deployment-index-table/last-deploy.vue'
import {GlTabs, GlModal, GlFormInput, GlFormGroup} from '@gitlab/ui'
import {mapGetters, mapActions, mapMutations} from 'vuex'
Expand All @@ -13,7 +13,6 @@ import { FLASH_TYPES } from 'oc_vue_shared/client_utils/oc-flash';
import Vue from 'vue'
import _ from 'lodash'
import * as routes from '../../router/constants'
import DashboardRouterLink from "../../components/dashboard-router-link.vue"
import MergeRequestsTable from './merge-requests-table.vue'
const standalone = window.gon.unfurl_gui
Expand Down Expand Up @@ -84,6 +83,7 @@ const tabFilters = [
export default {
components: {
TableComponent,
CombinedCell,
EnvironmentCell,
ResourceCell,
DeploymentControls,
Expand All @@ -94,8 +94,6 @@ export default {
EnvironmentSelection,
GlFormInput,
GlFormGroup,
DeploymentStatusIcon,
DashboardRouterLink,
MergeRequestsTable,
AutostopInner,
LocalDeploy
Expand Down Expand Up @@ -757,18 +755,7 @@ export default {
</div>
</template>
<template #deployment="scope">
<div class="d-flex">
<deployment-status-icon width="40px" :scope="scope" />
<div v-if="scope.item.context.application" style="display: flex; flex-direction: column;" :class="{'hash-fragment': `#${scope.item.context.deployment.name}` == $route.hash}">
<dashboard-router-link :noRouter="noRouter" :href="noRouter? deploymentItem(scope, 'viewableLink'): deploymentItem(scope, 'viewableTo')">
<b>{{scope.item.context.deployment.title}}:</b>
</dashboard-router-link>
<a :href="`/${scope.item.context.deployment.projectPath}`">
({{scope.item.context.application.title}})
</a>
</div>
</div>
<combined-cell v-if="scope.item.context.deployment" :noRouter="noRouter" :scope="scope" :application="scope.item.context.application" :deployment="scope.item.context.deployment" :environment="scope.item.context.environment"/>
</template>
<!--template #resource$empty="scope">
<div v-if="hasDeployPath(scope)">{{__('Not yet deployed')}}</div>
Expand Down
3 changes: 3 additions & 0 deletions packages/oc-pages/dashboard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {setupTheme} from 'oc_vue_shared/theme'
import {OcComponents} from 'oc_vue_shared/components/oc/plugin'
import {Popover as ElPopover, Loading as ElLoading} from 'element-ui'
import '../project_overview/assets/global.css' // TODO move this somewhere better
import {normpath} from 'oc_vue_shared/lib/normalize'

Vue.use(GlToast);
Vue.use(OcComponents)
Expand All @@ -31,6 +32,8 @@ export default (elemId='js-table-component') => {
import('./layout-fix.css')
const element = document.getElementById(elemId);
window.gon = {...window.gon, ...element.dataset}
window.gon.home_project = normpath(window.gon.home_project)
window.gon.working_dir_project = normpath(window.gon.working_dir_project)

if(window.Cypress || sessionStorage['debug'] || sessionStorage['unfurl-gui:state']) {
window.$store = store
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ export default class DeploymentItem {

get readonlyLink() { return `/${this.projectPath}/-/deployments/${this.environment.name}/${this.deployment.name}`}
get editableLink() {
let result = `/${this.deployment.projectPath}/deployment-drafts/${encodeURIComponent(this.projectPath)}/${this.environment.name}/${this.deployment.name}?fn=${this.deployment.title}`
let overviewPath = this.deployment.projectPath
if(window.gon.unfurl_gui) {
overviewPath += '/-/overview'
}
let result = `/${overviewPath}/deployment-drafts/${encodeURIComponent(this.projectPath)}/${this.environment.name}/${this.deployment.name}?fn=${this.deployment.title}`
if(this.deployment.branch) {
result += `&bprev=${this.deployment.branch}`
}
Expand Down
2 changes: 2 additions & 0 deletions packages/oc-pages/project_overview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export default (elemId='js-oc-project-overview') => {
} = element.dataset;

projectPath = normpath(projectPath)
window.gon.home_project = normpath(window.gon.home_project)
window.gon.working_dir_project = normpath(window.gon.working_dir_project)
const base = window.location.pathname.includes('/-/overview') ?
`${projectPath}/-/overview` : projectPath

Expand Down
5 changes: 3 additions & 2 deletions packages/oc-pages/project_overview/store/modules/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {fetchProjectInfo} from 'oc_vue_shared/client_utils/projects'
import {createFlash, hideLastFlash, FLASH_TYPES} from 'oc_vue_shared/client_utils/oc-flash'
import {unfurlServerUrlOverride} from 'oc_vue_shared/storage-keys'
import {lookupKey} from 'oc_vue_shared/storage-keys'
import {normpath} from 'oc_vue_shared/lib/normalize'

const DEFAULT_ROUTER_HOOK = (to, from, next) => next()

Expand Down Expand Up @@ -67,11 +68,11 @@ const mutations = {
const getters = {
getRouterHook(state) {return state.routerHook},
getCurrentNamespace(state, getters) {
if(window.gon.home_project !== null) return state.namespace || lookupKey('defaultNamespace') || getters.getUsername
if(window.gon.home_project !== null) return normpath(state.namespace || lookupKey('defaultNamespace') || getters.getUsername)
return null
},
getHomeProjectPath(state, getters) {
if(window.gon.home_project !== null) return `${getters.getCurrentNamespace}/${state.dashboard || USER_HOME_PROJECT}`
if(window.gon.home_project !== null) return normpath(`${getters.getCurrentNamespace}/${state.dashboard || USER_HOME_PROJECT}`)
return null
},
getHomeProjectName(state) {
Expand Down
Loading

0 comments on commit 648c5d6

Please sign in to comment.