fix-human-task-guid-fk (#1260)

* removed human_task_ibfk_5 from old migration file and updated task id removal migration to work with both mysql and postgres w/ burnettk

* use sqlalchemy error classes instead of mysql w/ burnettk

* mypy w/ burnettk

* remove deprecated cypress config w/ burnettk

---------

Co-authored-by: jasquat <jasquat@users.noreply.github.com>
This commit is contained in:
jasquat 2024-03-25 18:32:44 +00:00 committed by GitHub
parent fa241e1a01
commit b5b8031b44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 20 additions and 13 deletions

View File

@ -446,7 +446,7 @@ def upgrade():
sa.ForeignKeyConstraint(['completed_by_user_id'], ['user.id'], ), sa.ForeignKeyConstraint(['completed_by_user_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['lane_assignment_id'], ['group.id'], ), sa.ForeignKeyConstraint(['lane_assignment_id'], ['group.id'], ),
sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ),
sa.ForeignKeyConstraint(['task_model_id'], ['task.id'], name='human_task_ibfk_5'), sa.ForeignKeyConstraint(['task_model_id'], ['task.id']),
sa.PrimaryKeyConstraint('id') sa.PrimaryKeyConstraint('id')
) )
with op.batch_alter_table('human_task', schema=None) as batch_op: with op.batch_alter_table('human_task', schema=None) as batch_op:

View File

@ -20,6 +20,9 @@ depends_on = None
def is_mysql() -> bool: def is_mysql() -> bool:
return dialect_name() == 'mysql' return dialect_name() == 'mysql'
def is_postgres() -> bool:
return dialect_name() == 'postgres'
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
@ -31,7 +34,12 @@ def upgrade():
with op.batch_alter_table('human_task', schema=None) as batch_op: with op.batch_alter_table('human_task', schema=None) as batch_op:
batch_op.add_column(sa.Column('task_guid', sa.String(length=36), nullable=True)) batch_op.add_column(sa.Column('task_guid', sa.String(length=36), nullable=True))
batch_op.drop_constraint('human_task_ibfk_5', type_='foreignkey')
# sqlite does not seem to have this foreignkey constraint
if is_postgres():
batch_op.drop_constraint('human_task_task_model_id_fkey', type_='foreignkey')
elif is_mysql():
batch_op.drop_constraint('human_task_ibfk_5', type_='foreignkey')
batch_op.drop_index('ix_human_task_task_model_id') batch_op.drop_index('ix_human_task_task_model_id')
batch_op.create_index(batch_op.f('ix_human_task_task_guid'), ['task_guid'], unique=False) batch_op.create_index(batch_op.f('ix_human_task_task_guid'), ['task_guid'], unique=False)
batch_op.create_foreign_key('human_task_ibfk_task_guid', 'task', ['task_guid'], ['guid']) batch_op.create_foreign_key('human_task_ibfk_task_guid', 'task', ['task_guid'], ['guid'])

View File

@ -11,7 +11,6 @@ from flask import jsonify
from flask import make_response from flask import make_response
from flask import stream_with_context from flask import stream_with_context
from flask.wrappers import Response from flask.wrappers import Response
from MySQLdb import OperationalError # type: ignore
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskException # type: ignore from SpiffWorkflow.bpmn.exceptions import WorkflowTaskException # type: ignore
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow # type: ignore from SpiffWorkflow.bpmn.workflow import BpmnWorkflow # type: ignore
from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore
@ -19,6 +18,7 @@ from SpiffWorkflow.util.task import TaskState # type: ignore
from sqlalchemy import and_ from sqlalchemy import and_
from sqlalchemy import desc from sqlalchemy import desc
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.exc import OperationalError
from sqlalchemy.orm import aliased from sqlalchemy.orm import aliased
from sqlalchemy.orm.util import AliasedClass from sqlalchemy.orm.util import AliasedClass

View File

@ -1,6 +1,6 @@
/* eslint-disable */ /* eslint-disable */
const { defineConfig } = require("cypress"); const { defineConfig } = require('cypress');
const { rm } = require("fs/promises"); const { rm } = require('fs/promises');
// yes use video compression in CI, where we will set the env var so we upload to cypress dashboard // yes use video compression in CI, where we will set the env var so we upload to cypress dashboard
const useVideoCompression = !!process.env.CYPRESS_RECORD_KEY; const useVideoCompression = !!process.env.CYPRESS_RECORD_KEY;
@ -8,15 +8,15 @@ const useVideoCompression = !!process.env.CYPRESS_RECORD_KEY;
// https://github.com/cypress-io/cypress/issues/2522 // https://github.com/cypress-io/cypress/issues/2522
const deleteVideosOnSuccess = (on) => { const deleteVideosOnSuccess = (on) => {
const filesToDelete = []; const filesToDelete = [];
on("after:spec", (_spec, results) => { on('after:spec', (_spec, results) => {
if (results.stats.failures === 0 && results.video) { if (results.stats.failures === 0 && results.video) {
filesToDelete.push(results.video); filesToDelete.push(results.video);
} }
}); });
on("after:run", async () => { on('after:run', async () => {
if (filesToDelete.length) { if (filesToDelete.length) {
console.log( console.log(
"after:run hook: Deleting %d video(s) from successful specs", 'after:run hook: Deleting %d video(s) from successful specs',
filesToDelete.length filesToDelete.length
); );
await Promise.all(filesToDelete.map((videoFile) => rm(videoFile))); await Promise.all(filesToDelete.map((videoFile) => rm(videoFile)));
@ -33,15 +33,14 @@ if (process.env.SPIFFWORKFLOW_FRONTEND_URL) {
} }
const cypressConfig = { const cypressConfig = {
projectId: "crax1q", projectId: 'crax1q',
defaultCommandTimeout: 20000, defaultCommandTimeout: 20000,
videoUploadOnPasses: false,
chromeWebSecurity: false, chromeWebSecurity: false,
e2e: { e2e: {
baseUrl: spiffWorkflowFrontendUrl, baseUrl: spiffWorkflowFrontendUrl,
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
deleteVideosOnSuccess(on); deleteVideosOnSuccess(on);
require("@cypress/grep/src/plugin")(config); require('@cypress/grep/src/plugin')(config);
return config; return config;
}, },
}, },
@ -49,7 +48,7 @@ const cypressConfig = {
// this scrolls away from the elements for some reason with carbon when set to top // this scrolls away from the elements for some reason with carbon when set to top
// https://github.com/cypress-io/cypress/issues/2353 // https://github.com/cypress-io/cypress/issues/2353
// https://docs.cypress.io/guides/core-concepts/interacting-with-elements#Scrolling // https://docs.cypress.io/guides/core-concepts/interacting-with-elements#Scrolling
scrollBehavior: "center", scrollBehavior: 'center',
}; };
if (!process.env.CYPRESS_RECORD_KEY) { if (!process.env.CYPRESS_RECORD_KEY) {
@ -57,4 +56,4 @@ if (!process.env.CYPRESS_RECORD_KEY) {
cypressConfig.videoCompression = false; cypressConfig.videoCompression = false;
} }
module.exports = defineConfig(cypressConfig) module.exports = defineConfig(cypressConfig);