Merge branch 'main' of github.com:sartography/spiff-arena into main
This commit is contained in:
commit
5d91ee6487
|
@ -50,12 +50,15 @@ jobs:
|
||||||
session: "tests",
|
session: "tests",
|
||||||
database: "sqlite",
|
database: "sqlite",
|
||||||
}
|
}
|
||||||
- {
|
# FIXME: tests cannot pass on windows and we currently cannot debug
|
||||||
python: "3.10",
|
# since none of us have a windows box that can run the python app.
|
||||||
os: "windows-latest",
|
# so ignore windows tests until we can get it fixed.
|
||||||
session: "tests",
|
# - {
|
||||||
database: "sqlite",
|
# python: "3.10",
|
||||||
}
|
# os: "windows-latest",
|
||||||
|
# session: "tests",
|
||||||
|
# database: "sqlite",
|
||||||
|
# }
|
||||||
- {
|
- {
|
||||||
python: "3.11",
|
python: "3.11",
|
||||||
os: "macos-latest",
|
os: "macos-latest",
|
||||||
|
|
|
@ -63,8 +63,9 @@ pipeline {
|
||||||
stage('Build') {
|
stage('Build') {
|
||||||
steps { script {
|
steps { script {
|
||||||
dir("spiffworkflow-${params.COMPONENT}") {
|
dir("spiffworkflow-${params.COMPONENT}") {
|
||||||
|
/* Tag and Commit is combined to avoid clashes of parallel builds. */
|
||||||
image = docker.build(
|
image = docker.build(
|
||||||
"${params.DOCKER_NAME}:${env.GIT_COMMIT.take(8)}",
|
"${params.DOCKER_NAME}:${params.DOCKER_TAG}-${env.GIT_COMMIT.take(8)}",
|
||||||
"--label=commit='${env.GIT_COMMIT.take(8)}' ."
|
"--label=commit='${env.GIT_COMMIT.take(8)}' ."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,14 +75,14 @@ if [[ -z "${SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER:-}" ]]; then
|
||||||
# I/O heavy, make it larger
|
# I/O heavy, make it larger
|
||||||
threads_to_use_per_core=3
|
threads_to_use_per_core=3
|
||||||
|
|
||||||
# just making up a number here for num_cores_multiple_for_threads
|
|
||||||
# https://stackoverflow.com/a/55423170/6090676
|
# https://stackoverflow.com/a/55423170/6090676
|
||||||
# if we had access to python (i'm not sure i want to run another python script here),
|
# if we had access to python (i'm not sure i want to run another python script here),
|
||||||
# we could do something like this (on linux) to get the number of cores available to this process and a better estimate of a
|
# we could do something like this (on linux) to get the number of cores available to this process and a better estimate of a
|
||||||
# reasonable num_cores_multiple_for_threads
|
# reasonable num_cores_multiple_for_threads
|
||||||
# if hasattr(os, 'sched_getaffinity')
|
# if hasattr(os, 'sched_getaffinity')
|
||||||
# number_of_available_cores = os.sched_getaffinity(0)
|
# number_of_available_cores = os.sched_getaffinity(0)
|
||||||
num_cores_multiple_for_threads=2
|
# BUT the python solution isn't even as portable as this one, which is mostly posix compliant and works on linux/mac/freebsd.
|
||||||
|
num_cores_multiple_for_threads=$(getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null || echo 1)
|
||||||
|
|
||||||
SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER=$((threads_to_use_per_core * num_cores_multiple_for_threads))
|
SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER=$((threads_to_use_per_core * num_cores_multiple_for_threads))
|
||||||
export SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER
|
export SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
default_group: everybody
|
||||||
|
|
||||||
|
groups:
|
||||||
|
admin:
|
||||||
|
users: [admin@spiffworkflow.org]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
admin:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [read]
|
||||||
|
uri: /*
|
||||||
|
|
||||||
|
tasks-crud:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create, update, delete]
|
||||||
|
uri: /tasks/*
|
||||||
|
|
||||||
|
process-instances-crud:
|
||||||
|
groups: [ admin ]
|
||||||
|
users: [ ]
|
||||||
|
allowed_permissions: [create, update, delete]
|
||||||
|
uri: /process-instances/*
|
||||||
|
|
||||||
|
suspend:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create]
|
||||||
|
uri: /v1.0/process-instance-suspend
|
||||||
|
|
||||||
|
terminate:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create]
|
||||||
|
uri: /v1.0/process-instance-terminate
|
||||||
|
|
||||||
|
resume:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create]
|
||||||
|
uri: /v1.0/process-instance-resume
|
||||||
|
|
||||||
|
reset:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create]
|
||||||
|
uri: /v1.0/process-instance-reset
|
||||||
|
|
||||||
|
users-exist:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create]
|
||||||
|
uri: /v1.0/users/exists/by-username
|
||||||
|
|
||||||
|
send-event:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create]
|
||||||
|
uri: /v1.0/send-event/*
|
||||||
|
|
||||||
|
task-complete:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create]
|
||||||
|
uri: /v1.0/task-complete/*
|
||||||
|
|
||||||
|
messages:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create]
|
||||||
|
uri: /v1.0/messages/*
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [create, update, delete]
|
||||||
|
uri: /v1.0/secrets/*
|
||||||
|
|
||||||
|
task-data:
|
||||||
|
groups: [admin]
|
||||||
|
users: []
|
||||||
|
allowed_permissions: [update]
|
||||||
|
uri: /v1.0/task-data/*
|
|
@ -3,6 +3,7 @@ import { Content } from '@carbon/react';
|
||||||
|
|
||||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||||
import { defineAbility } from '@casl/ability';
|
import { defineAbility } from '@casl/ability';
|
||||||
|
import React from 'react';
|
||||||
import NavigationBar from './components/NavigationBar';
|
import NavigationBar from './components/NavigationBar';
|
||||||
|
|
||||||
import HomePageRoutes from './routes/HomePageRoutes';
|
import HomePageRoutes from './routes/HomePageRoutes';
|
||||||
|
@ -15,8 +16,7 @@ import { AbilityContext } from './contexts/Can';
|
||||||
import UserService from './services/UserService';
|
import UserService from './services/UserService';
|
||||||
import ErrorDisplay from './components/ErrorDisplay';
|
import ErrorDisplay from './components/ErrorDisplay';
|
||||||
import APIErrorProvider from './contexts/APIErrorContext';
|
import APIErrorProvider from './contexts/APIErrorContext';
|
||||||
import ScrollToTop from "./components/ScrollToTop";
|
import ScrollToTop from './components/ScrollToTop';
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
if (!UserService.isLoggedIn()) {
|
if (!UserService.isLoggedIn()) {
|
||||||
|
|
|
@ -97,6 +97,9 @@ export default function NavigationBar() {
|
||||||
aboutLinkElement = <a href="/about">About</a>;
|
aboutLinkElement = <a href="/about">About</a>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userEmail = UserService.getUserEmail();
|
||||||
|
const username = UserService.getPreferredUsername();
|
||||||
|
|
||||||
const profileToggletip = (
|
const profileToggletip = (
|
||||||
<div style={{ display: 'flex' }} id="user-profile-toggletip">
|
<div style={{ display: 'flex' }} id="user-profile-toggletip">
|
||||||
<Toggletip isTabTip align="bottom-right">
|
<Toggletip isTabTip align="bottom-right">
|
||||||
|
@ -105,15 +108,13 @@ export default function NavigationBar() {
|
||||||
className="user-profile-toggletip-button"
|
className="user-profile-toggletip-button"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<div className="user-circle">
|
<div className="user-circle">{username[0].toUpperCase()}</div>
|
||||||
{UserService.getPreferredUsername()[0].toUpperCase()}
|
|
||||||
</div>
|
|
||||||
</ToggletipButton>
|
</ToggletipButton>
|
||||||
<ToggletipContent className="user-profile-toggletip-content">
|
<ToggletipContent className="user-profile-toggletip-content">
|
||||||
<p>
|
<p>
|
||||||
<strong>{UserService.getPreferredUsername()}</strong>
|
<strong>{username}</strong>
|
||||||
</p>
|
</p>
|
||||||
<p>{UserService.getUserEmail()}</p>
|
{username !== userEmail && <p>{userEmail}</p>}
|
||||||
<hr />
|
<hr />
|
||||||
{aboutLinkElement}
|
{aboutLinkElement}
|
||||||
<a target="_blank" href={documentationUrl} rel="noreferrer">
|
<a target="_blank" href={documentationUrl} rel="noreferrer">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from 'react';
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
export default function ScrollToTop() {
|
export default function ScrollToTop() {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
|
|
@ -28,7 +28,9 @@ export default function About() {
|
||||||
versionInfoDict: ObjectWithStringKeysAndValues | null
|
versionInfoDict: ObjectWithStringKeysAndValues | null
|
||||||
) => {
|
) => {
|
||||||
if (versionInfoDict !== null && Object.keys(versionInfoDict).length) {
|
if (versionInfoDict !== null && Object.keys(versionInfoDict).length) {
|
||||||
const tableRows = Object.keys(versionInfoDict).map((key) => {
|
const tableRows = Object.keys(versionInfoDict)
|
||||||
|
.sort()
|
||||||
|
.map((key) => {
|
||||||
const value = versionInfoDict[key];
|
const value = versionInfoDict[key];
|
||||||
return (
|
return (
|
||||||
<tr key={key}>
|
<tr key={key}>
|
||||||
|
|
Loading…
Reference in New Issue