fix: .onedev-buildspec kaniko build validation issue (OD-2564)

This commit is contained in:
Robin Shen 2025-09-26 21:34:43 +08:00
parent a68f9784b0
commit e3b23bd5ba
3 changed files with 284 additions and 8 deletions

View File

@ -46,7 +46,6 @@ import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Throwables;
import io.onedev.commons.utils.ExplicitException;
import io.onedev.commons.utils.StringUtils;
import io.onedev.server.SubscriptionManager;
import io.onedev.server.buildspec.BuildSpec;
@ -73,7 +72,6 @@ import io.onedev.server.entitymanager.UserManager;
import io.onedev.server.entityreference.BuildReference;
import io.onedev.server.entityreference.IssueReference;
import io.onedev.server.entityreference.PullRequestReference;
import io.onedev.server.exception.ExceptionUtils;
import io.onedev.server.exception.InvalidIssueFieldsException;
import io.onedev.server.exception.InvalidReferenceException;
import io.onedev.server.exception.IssueLinkValidationException;
@ -2160,12 +2158,7 @@ public class McpHelperResource {
return Response.status(NOT_ACCEPTABLE).entity(Joiner.on("\n").join(validationErrors) + schemaNotice).build();
}
} catch (Exception e) {
var explicitException = ExceptionUtils.find(e, ExplicitException.class);
if (explicitException != null) {
return Response.status(NOT_ACCEPTABLE).entity(explicitException.getMessage() + schemaNotice).build();
} else {
return Response.status(NOT_ACCEPTABLE).entity(Throwables.getStackTraceAsString(e) + schemaNotice).build();
}
return Response.status(NOT_ACCEPTABLE).entity(Throwables.getStackTraceAsString(e) + schemaNotice).build();
} finally {
Project.pop();
}

View File

@ -0,0 +1,244 @@
/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.internal.engine;
import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.validator.internal.metadata.aggregated.rule.MethodConfigurationRule;
import org.hibernate.validator.internal.metadata.aggregated.rule.OverridingMethodMustNotAlterParameterConstraints;
import org.hibernate.validator.internal.metadata.aggregated.rule.ParallelMethodsMustNotDefineGroupConversionForCascadedReturnValue;
import org.hibernate.validator.internal.metadata.aggregated.rule.ParallelMethodsMustNotDefineParameterConstraints;
import org.hibernate.validator.internal.metadata.aggregated.rule.ReturnValueMayOnlyBeMarkedOnceAsCascadedPerHierarchyLine;
import org.hibernate.validator.internal.metadata.aggregated.rule.VoidMethodsMustNotBeReturnValueConstrained;
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.stereotypes.Immutable;
/**
* These properties modify the behavior of the {@code Validator} with respect to the Jakarta Bean Validation
* specification section 5.6.5. In particular:
* <pre>
* "Out of the box, a conforming Bean Validation provider must throw a
* ConstraintDeclarationException when discovering that any of these rules are violated.
* In addition providers may implement alternative, potentially more liberal, approaches
* for handling constrained methods in inheritance hierarchies. Possible means for activating
* such alternative behavior include provider-specific configuration properties or annotations.
* Note that client code relying on such alternative behavior is not portable between Bean
* Validation providers."
* </pre>
*
* @author Chris Beckey &lt;cbeckey@paypal.com&gt;
* @author Guillaume Smet
*/
public class MethodValidationConfiguration {
private boolean allowOverridingMethodAlterParameterConstraint = false;
private boolean allowMultipleCascadedValidationOnReturnValues = false;
private boolean allowParallelMethodsDefineParameterConstraints = false;
@Immutable
private Set<MethodConfigurationRule> configuredRuleSet;
private MethodValidationConfiguration(boolean allowOverridingMethodAlterParameterConstraint, boolean allowMultipleCascadedValidationOnReturnValues,
boolean allowParallelMethodsDefineParameterConstraints) {
this.allowOverridingMethodAlterParameterConstraint = allowOverridingMethodAlterParameterConstraint;
// We should allow @Valid on both super methods and sub methods, as we modified validator to
// completely ignore constraint annotations in super methods
this.allowMultipleCascadedValidationOnReturnValues = true;
this.allowParallelMethodsDefineParameterConstraints = allowParallelMethodsDefineParameterConstraints;
this.configuredRuleSet = buildConfiguredRuleSet( allowOverridingMethodAlterParameterConstraint, allowMultipleCascadedValidationOnReturnValues,
allowParallelMethodsDefineParameterConstraints );
}
/**
* @return {@code true} if more than one return value within a class hierarchy can be marked for cascaded
* validation, {@code false} otherwise.
*/
public boolean isAllowOverridingMethodAlterParameterConstraint() {
return this.allowOverridingMethodAlterParameterConstraint;
}
/**
* @return {@code true} if more than one return value within a class hierarchy can be marked for cascaded
* validation, {@code false} otherwise.
*/
public boolean isAllowMultipleCascadedValidationOnReturnValues() {
return this.allowMultipleCascadedValidationOnReturnValues;
}
/**
* @return {@code true} if constraints on methods in parallel class hierarchy are allowed, {@code false} otherwise.
*/
public boolean isAllowParallelMethodsDefineParameterConstraints() {
return this.allowParallelMethodsDefineParameterConstraints;
}
/**
* Return an unmodifiable Set of MethodConfigurationRule that are to be
* enforced based on the configuration.
*
* @return a set of method configuration rules based on this configuration state
*/
public Set<MethodConfigurationRule> getConfiguredRuleSet() {
return configuredRuleSet;
}
private static Set<MethodConfigurationRule> buildConfiguredRuleSet(boolean allowOverridingMethodAlterParameterConstraint,
boolean allowMultipleCascadedValidationOnReturnValues, boolean allowParallelMethodsDefineParameterConstraints) {
HashSet<MethodConfigurationRule> result = newHashSet( 5 );
if ( !allowOverridingMethodAlterParameterConstraint ) {
result.add( new OverridingMethodMustNotAlterParameterConstraints() );
}
if ( !allowParallelMethodsDefineParameterConstraints ) {
result.add( new ParallelMethodsMustNotDefineParameterConstraints() );
}
result.add( new VoidMethodsMustNotBeReturnValueConstrained() );
if ( !allowMultipleCascadedValidationOnReturnValues ) {
result.add( new ReturnValueMayOnlyBeMarkedOnceAsCascadedPerHierarchyLine() );
}
result.add( new ParallelMethodsMustNotDefineGroupConversionForCascadedReturnValue() );
return CollectionHelper.toImmutableSet( result );
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ( allowMultipleCascadedValidationOnReturnValues ? 1231 : 1237 );
result = prime * result + ( allowOverridingMethodAlterParameterConstraint ? 1231 : 1237 );
result = prime * result + ( allowParallelMethodsDefineParameterConstraints ? 1231 : 1237 );
return result;
}
@Override
public boolean equals(Object obj) {
if ( this == obj ) {
return true;
}
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
MethodValidationConfiguration other = (MethodValidationConfiguration) obj;
if ( allowMultipleCascadedValidationOnReturnValues != other.allowMultipleCascadedValidationOnReturnValues ) {
return false;
}
if ( allowOverridingMethodAlterParameterConstraint != other.allowOverridingMethodAlterParameterConstraint ) {
return false;
}
if ( allowParallelMethodsDefineParameterConstraints != other.allowParallelMethodsDefineParameterConstraints ) {
return false;
}
return true;
}
public static class Builder {
private boolean allowOverridingMethodAlterParameterConstraint = false;
private boolean allowMultipleCascadedValidationOnReturnValues = false;
private boolean allowParallelMethodsDefineParameterConstraints = false;
public Builder() {
}
public Builder(MethodValidationConfiguration template) {
allowOverridingMethodAlterParameterConstraint = template.allowOverridingMethodAlterParameterConstraint;
allowMultipleCascadedValidationOnReturnValues = template.allowMultipleCascadedValidationOnReturnValues;
allowParallelMethodsDefineParameterConstraints = template.allowParallelMethodsDefineParameterConstraints;
}
/**
* Define whether overriding methods that override constraints should throw a {@code ConstraintDefinitionException}.
* The default value is {@code false}, i.e. do not allow.
*
* See Section 5.6.5 of the Jakarta Bean Validation Specification, specifically
* <pre>
* "In sub types (be it sub classes/interfaces or interface implementations), no parameter constraints may
* be declared on overridden or implemented methods, nor may parameters be marked for cascaded validation.
* This would pose a strengthening of preconditions to be fulfilled by the caller."
* </pre>
*
* @param allow flag determining whether validation will allow overriding to alter parameter constraints.
*
* @return {@code this} following the chaining method pattern
*/
public Builder allowOverridingMethodAlterParameterConstraint(boolean allow) {
this.allowOverridingMethodAlterParameterConstraint = allow;
return this;
}
/**
* Define whether more than one constraint on a return value may be marked for cascading validation are allowed.
* The default value is {@code false}, i.e. do not allow.
*
* "One must not mark a method return value for cascaded validation more than once in a line of a class hierarchy.
* In other words, overriding methods on sub types (be it sub classes/interfaces or interface implementations)
* cannot mark the return value for cascaded validation if the return value has already been marked on the
* overridden method of the super type or interface."
*
* @param allow flag determining whether validation will allow multiple cascaded validation on return values.
*
* @return {@code this} following the chaining method pattern
*/
public Builder allowMultipleCascadedValidationOnReturnValues(boolean allow) {
this.allowMultipleCascadedValidationOnReturnValues = allow;
return this;
}
/**
* Define whether parallel methods that define constraints should throw a {@code ConstraintDefinitionException}. The
* default value is {@code false}, i.e. do not allow.
*
* See Section 5.6.5 of the Jakarta Bean Validation Specification, specifically
* "If a sub type overrides/implements a method originally defined in several parallel types of the hierarchy
* (e.g. two interfaces not extending each other, or a class and an interface not implemented by said class),
* no parameter constraints may be declared for that method at all nor parameters be marked for cascaded validation.
* This again is to avoid an unexpected strengthening of preconditions to be fulfilled by the caller."
*
* @param allow flag determining whether validation will allow parameter constraints in parallel hierarchies
*
* @return {@code this} following the chaining method pattern
*/
public Builder allowParallelMethodsDefineParameterConstraints(boolean allow) {
this.allowParallelMethodsDefineParameterConstraints = allow;
return this;
}
public boolean isAllowOverridingMethodAlterParameterConstraint() {
return allowOverridingMethodAlterParameterConstraint;
}
public boolean isAllowMultipleCascadedValidationOnReturnValues() {
return allowMultipleCascadedValidationOnReturnValues;
}
public boolean isAllowParallelMethodsDefineParameterConstraints() {
return allowParallelMethodsDefineParameterConstraints;
}
public MethodValidationConfiguration build() {
return new MethodValidationConfiguration(
allowOverridingMethodAlterParameterConstraint,
allowMultipleCascadedValidationOnReturnValues,
allowParallelMethodsDefineParameterConstraints
);
}
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.validator.internal.engine;
import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES;
import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
@ -69,7 +70,9 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraint;
import org.hibernate.validator.internal.metadata.facets.Cascadable;
import org.hibernate.validator.internal.metadata.facets.Validatable;
import org.hibernate.validator.internal.metadata.location.AbstractPropertyConstraintLocation;
import org.hibernate.validator.internal.metadata.location.ConstraintLocation;
import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind;
import org.hibernate.validator.internal.metadata.location.GetterConstraintLocation;
import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation;
import org.hibernate.validator.internal.util.Contracts;
import org.hibernate.validator.internal.util.ExecutableHelper;
@ -1311,6 +1314,23 @@ public class ValidatorImpl implements Validator, ExecutableValidator {
return ValueContexts.getLocalExecutionContextForValueValidation( validatorScopedContext.getParameterNameProvider(), beanMetaData, propertyPath );
}
/**
* Check if a constraint comes from a superclass method that has been overridden
* in the current bean class. If so, the constraint should be ignored.
*/
private boolean isConstraintFromOverriddenMethod(ConstraintLocation location, Class<?> beanClass, Class<? extends Annotation> constraintAnnotationType) {
if (location instanceof GetterConstraintLocation) {
GetterConstraintLocation getterLocation = (GetterConstraintLocation) location;
String propertyName = getterLocation.getPropertyName();
Method getter = BeanUtils.findGetter(beanClass, propertyName);
if (getter != null) {
return getter.getAnnotation(constraintAnnotationType) == null;
}
}
return false;
}
private boolean isValidationRequired(BaseBeanValidationContext<?> validationContext,
ValueContext<?, ?> valueContext,
MetaConstraint<?> metaConstraint) {
@ -1319,6 +1339,10 @@ public class ValidatorImpl implements Validator, ExecutableValidator {
location = ((TypeArgumentConstraintLocation) location).getOuterDelegate();
}
if (location instanceof AbstractPropertyConstraintLocation && valueContext.getCurrentBean() != null) {
// Check if this constraint comes from a superclass method that has been overridden
if (isConstraintFromOverriddenMethod(location, valueContext.getCurrentBean().getClass(), metaConstraint.getDescriptor().getAnnotationType())) {
return false; // Skip validation for constraints from overridden superclass methods
}
var bean = valueContext.getCurrentBean();
var propertyName = ((AbstractPropertyConstraintLocation<?>) location).getPropertyName();
var getter = BeanUtils.findGetter(bean.getClass(), propertyName);
@ -1428,6 +1452,16 @@ public class ValidatorImpl implements Validator, ExecutableValidator {
|| isReturnValueValidation( path );
}
private boolean isCascadeFromOverriddenMethod(Cascadable cascadable, Class<?> beanClass, String propertyName) {
if (cascadable.getConstraintLocationKind() == ConstraintLocationKind.GETTER && propertyName != null) {
Method getter = BeanUtils.findGetter(beanClass, propertyName);
if (getter != null) {
return getter.getAnnotation(javax.validation.Valid.class) == null;
}
}
return false;
}
private boolean isCascadeValidationRequired(BaseBeanValidationContext<?> validationContext, ValueContext<?, Object> valueContext, Cascadable cascadable) {
if (valueContext.getCurrentBean() != null && cascadable.getConstraintLocationKind() == ConstraintLocationKind.GETTER) {
var bean = valueContext.getCurrentBean();
@ -1435,6 +1469,11 @@ public class ValidatorImpl implements Validator, ExecutableValidator {
var leafNode = currentPath.getLeafNode();
if (leafNode != null) {
var propertyName = leafNode.getName();
// Check if this cascade validation comes from a superclass method that has been overridden
if (isCascadeFromOverriddenMethod(cascadable, bean.getClass(), propertyName)) {
return false; // Skip cascade validation for @Valid annotations from overridden superclass methods
}
Method getter = BeanUtils.findGetter(bean.getClass(), propertyName);
if (getter == null) {
throw new ExplicitException("Getter not found for property: " + propertyName);