summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/pipeline/expression
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/ci/pipeline/expression')
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/matches.rb29
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb33
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/string.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/variable.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexer.rb8
-rw-r--r--lib/gitlab/ci/pipeline/expression/statement.rb24
6 files changed, 86 insertions, 12 deletions
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb b/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
new file mode 100644
index 00000000000..10957598f76
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
@@ -0,0 +1,29 @@
+module Gitlab
+ module Ci
+ module Pipeline
+ module Expression
+ module Lexeme
+ class Matches < Lexeme::Operator
+ PATTERN = /=~/.freeze
+
+ def initialize(left, right)
+ @left = left
+ @right = right
+ end
+
+ def evaluate(variables = {})
+ text = @left.evaluate(variables)
+ regexp = @right.evaluate(variables)
+
+ regexp.scan(text.to_s).any?
+ end
+
+ def self.build(_value, behind, ahead)
+ new(behind, ahead)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb b/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb
new file mode 100644
index 00000000000..9b239c29ea4
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb
@@ -0,0 +1,33 @@
+module Gitlab
+ module Ci
+ module Pipeline
+ module Expression
+ module Lexeme
+ require_dependency 're2'
+
+ class Pattern < Lexeme::Value
+ PATTERN = %r{^/.+/[ismU]*$}.freeze
+
+ def initialize(regexp)
+ @value = regexp
+
+ unless Gitlab::UntrustedRegexp.valid?(@value)
+ raise Lexer::SyntaxError, 'Invalid regular expression!'
+ end
+ end
+
+ def evaluate(variables = {})
+ Gitlab::UntrustedRegexp.fabricate(@value)
+ rescue RegexpError
+ raise Expression::RuntimeError, 'Invalid regular expression!'
+ end
+
+ def self.build(string)
+ new(string)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/string.rb b/lib/gitlab/ci/pipeline/expression/lexeme/string.rb
index 48bde213d44..346c92dc51e 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/string.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/string.rb
@@ -4,7 +4,7 @@ module Gitlab
module Expression
module Lexeme
class String < Lexeme::Value
- PATTERN = /("(?<string>.+?)")|('(?<string>.+?)')/.freeze
+ PATTERN = /("(?<string>.*?)")|('(?<string>.*?)')/.freeze
def initialize(value)
@value = value
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb b/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb
index b781c15fd67..37643c8ef53 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb
@@ -11,7 +11,7 @@ module Gitlab
end
def evaluate(variables = {})
- HashWithIndifferentAccess.new(variables).fetch(@name, nil)
+ variables.with_indifferent_access.fetch(@name, nil)
end
def self.build(string)
diff --git a/lib/gitlab/ci/pipeline/expression/lexer.rb b/lib/gitlab/ci/pipeline/expression/lexer.rb
index e1c68b7c3c2..4cacb1e62c9 100644
--- a/lib/gitlab/ci/pipeline/expression/lexer.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexer.rb
@@ -5,15 +5,17 @@ module Gitlab
class Lexer
include ::Gitlab::Utils::StrongMemoize
+ SyntaxError = Class.new(Expression::ExpressionError)
+
LEXEMES = [
Expression::Lexeme::Variable,
Expression::Lexeme::String,
+ Expression::Lexeme::Pattern,
Expression::Lexeme::Null,
- Expression::Lexeme::Equals
+ Expression::Lexeme::Equals,
+ Expression::Lexeme::Matches
].freeze
- SyntaxError = Class.new(Statement::StatementError)
-
MAX_TOKENS = 100
def initialize(statement, max_tokens: MAX_TOKENS)
diff --git a/lib/gitlab/ci/pipeline/expression/statement.rb b/lib/gitlab/ci/pipeline/expression/statement.rb
index 4f0e101b730..b36f1e0f865 100644
--- a/lib/gitlab/ci/pipeline/expression/statement.rb
+++ b/lib/gitlab/ci/pipeline/expression/statement.rb
@@ -3,23 +3,21 @@ module Gitlab
module Pipeline
module Expression
class Statement
- StatementError = Class.new(StandardError)
+ StatementError = Class.new(Expression::ExpressionError)
GRAMMAR = [
+ %w[variable],
%w[variable equals string],
%w[variable equals variable],
%w[variable equals null],
%w[string equals variable],
%w[null equals variable],
- %w[variable]
+ %w[variable matches pattern]
].freeze
- def initialize(statement, pipeline)
+ def initialize(statement, variables = {})
@lexer = Expression::Lexer.new(statement)
-
- @variables = pipeline.variables.map do |variable|
- [variable.key, variable.value]
- end
+ @variables = variables.with_indifferent_access
end
def parse_tree
@@ -35,6 +33,18 @@ module Gitlab
def evaluate
parse_tree.evaluate(@variables.to_h)
end
+
+ def truthful?
+ evaluate.present?
+ rescue Expression::ExpressionError
+ false
+ end
+
+ def valid?
+ parse_tree.is_a?(Lexeme::Base)
+ rescue Expression::ExpressionError
+ false
+ end
end
end
end