You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by kl...@apache.org on 2022/12/13 12:23:21 UTC

[incubator-devlake] branch main updated: feat: add time filter and fix some bug for skipOnFail (#3916)

This is an automated email from the ASF dual-hosted git repository.

klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new 73e8dc53b feat: add time filter and fix some bug for skipOnFail (#3916)
73e8dc53b is described below

commit 73e8dc53b2c103793c22aac7ab1c66dc35e8819b
Author: Likyh <ya...@meri.co>
AuthorDate: Tue Dec 13 20:23:17 2022 +0800

    feat: add time filter and fix some bug for skipOnFail (#3916)
    
    * feat: add time filter and fix some bug for skipOnFail
    
    * fix: append nil checker; fix ci
    
    * fix: fix for unit-test
    
    * fix: fix for ci
    
    * fix: fix for ci
    
    * fix: fix for review (frontend)
    
    * fix: fix for review (backend)
    
    * fix: for review: move skipOnFail from task to pipeline
    
    * fix: fix for ci
    
    * fix: fix for review
---
 .editorconfig                                      |   2 +-
 config-ui/package-lock.json                        | 115 ++++++++++++++++-----
 config-ui/package.json                             |   1 +
 .../components/blueprints/StartFromSelector.tsx    | 107 +++++++++++++++++++
 .../blueprints/create-workflow/DataSync.jsx        |  13 +++
 .../src/components/pipelines/StageTaskName.jsx     |   4 +-
 config-ui/src/data/BlueprintWorkflow.js            |   8 +-
 config-ui/src/data/availablePlugins.js             |   9 +-
 config-ui/src/data/pipeline-config-samples/jira.js |   2 +-
 .../src/data/pipeline-config-samples/zentao.js     |   2 +-
 config-ui/src/hooks/useBlueprintManager.jsx        |  23 +++--
 config-ui/src/hooks/useDataScopesManager.jsx       |   2 +-
 config-ui/src/hooks/usePipelineManager.jsx         |  75 ++++++++------
 config-ui/src/index.css                            |   1 +
 .../blueprint/create/components/workflow/index.tsx |   4 +-
 .../blueprint/create/hooks/blueprint-context.ts    |   4 +
 .../blueprint/create/hooks/use-blueprint-value.ts  |  10 +-
 .../src/pages/blueprint/create/step-four/index.tsx |  18 +++-
 .../blueprint/create/step-one/example/jira.ts      |   2 +-
 .../src/pages/blueprints/blueprint-settings.jsx    |  12 ++-
 models/blueprint.go                                |  10 +-
 .../migrationscripts/20221107_add_skip_on_fail.go  |  10 +-
 models/pipeline.go                                 |   3 +
 models/task.go                                     |   1 -
 plugins/core/plugin_blueprint.go                   |  20 +++-
 plugins/dora/impl/impl.go                          |  12 ---
 plugins/github/api/blueprint_V200_test.go          |  14 ++-
 plugins/github/api/blueprint_v200.go               |   8 +-
 plugins/github/impl/impl.go                        |   8 +-
 plugins/github/tasks/cicd_run_collector.go         |   3 +-
 plugins/github_graphql/impl/impl.go                |   2 +-
 plugins/gitlab/api/blueprint_V200_test.go          |  11 +-
 plugins/gitlab/api/blueprint_v200.go               |  11 +-
 plugins/gitlab/impl/impl.go                        |   6 +-
 plugins/gitlab/tasks/issue_collector.go            |   5 +-
 plugins/gitlab/tasks/mr_collector.go               |   5 +-
 plugins/jenkins/api/blueprint_v200.go              |   9 +-
 plugins/jenkins/api/blueprint_v200_test.go         |   8 +-
 plugins/jenkins/impl/impl.go                       |   6 +-
 plugins/jira/api/blueprint_v200.go                 |   9 +-
 plugins/jira/api/blueprint_v200_test.go            |   8 +-
 plugins/jira/impl/impl.go                          |   6 +-
 plugins/tapd/impl/impl.go                          |   2 +-
 plugins/webhook/impl/impl.go                       |   2 +-
 runner/run_task.go                                 |   8 +-
 services/blueprint.go                              |  10 +-
 services/blueprint_makeplan_v100.go                |   1 -
 services/blueprint_makeplan_v200.go                |   7 +-
 services/blueprint_makeplan_v200_test.go           |   5 +-
 services/pipeline_helper.go                        |   3 +
 services/task.go                                   |   2 -
 51 files changed, 444 insertions(+), 185 deletions(-)

diff --git a/.editorconfig b/.editorconfig
index 135b3ac9b..91adc1af3 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -2,6 +2,6 @@
 indent_style = tab
 indent_size = 4
 
-[*.{js,jsx,yml,yaml}]
+[*.{js,jsx,ts,tsx,yml,yaml}]
 indent_style = space
 indent_size = 2
diff --git a/config-ui/package-lock.json b/config-ui/package-lock.json
index e96259041..07aacb8f7 100644
--- a/config-ui/package-lock.json
+++ b/config-ui/package-lock.json
@@ -1527,6 +1527,47 @@
         }
       }
     },
+    "@blueprintjs/datetime": {
+      "version": "4.4.8",
+      "resolved": "https://registry.npmmirror.com/@blueprintjs/datetime/-/datetime-4.4.8.tgz",
+      "integrity": "sha512-FbIOp8Snq6ZFY+JBmOLu7e0j/TF1enjxGGxfowzKbi+PtZDqrcpvRFo8tHVPv1Km30A1LdSw+EGDHtscomjwEw==",
+      "requires": {
+        "@blueprintjs/core": "^4.13.0",
+        "classnames": "^2.3.1",
+        "react-day-picker": "7.4.9",
+        "tslib": "~2.3.1"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.3.1",
+          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.1.tgz",
+          "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
+        }
+      }
+    },
+    "@blueprintjs/datetime2": {
+      "version": "0.9.6",
+      "resolved": "https://registry.npmmirror.com/@blueprintjs/datetime2/-/datetime2-0.9.6.tgz",
+      "integrity": "sha512-npO942mN454MKudbQ25176GBBSo+T2eOIKaSmIZk4YM2lG4ZgSK7IH6PPY8voKj3AWxWd9W7Gvz8ANtf8ZmKYQ==",
+      "requires": {
+        "@blueprintjs/core": "^4.13.0",
+        "@blueprintjs/datetime": "^4.4.8",
+        "@blueprintjs/popover2": "^1.10.2",
+        "@blueprintjs/select": "^4.8.12",
+        "classnames": "^2.3.1",
+        "date-fns": "^2.28.0",
+        "date-fns-tz": "^1.3.7",
+        "lodash": "^4.17.21",
+        "tslib": "~2.3.1"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.3.1",
+          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.1.tgz",
+          "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
+        }
+      }
+    },
     "@blueprintjs/icons": {
       "version": "4.11.0",
       "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-4.11.0.tgz",
@@ -3711,7 +3752,7 @@
     "amdefine": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
-      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+      "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==",
       "dev": true
     },
     "ansi-align": {
@@ -4006,7 +4047,7 @@
     "async-foreach": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
-      "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
+      "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==",
       "dev": true
     },
     "async-limiter": {
@@ -5535,7 +5576,7 @@
     "code-point-at": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
-      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==",
       "dev": true
     },
     "collect-v8-coverage": {
@@ -5753,7 +5794,7 @@
     "console-control-strings": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+      "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
       "dev": true
     },
     "constant-case": {
@@ -6695,6 +6736,16 @@
         "whatwg-url": "^8.0.0"
       }
     },
+    "date-fns": {
+      "version": "2.29.3",
+      "resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-2.29.3.tgz",
+      "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
+    },
+    "date-fns-tz": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npmmirror.com/date-fns-tz/-/date-fns-tz-1.3.7.tgz",
+      "integrity": "sha512-1t1b8zyJo+UI8aR+g3iqr5fkUHWpd58VBx8J/ZSQ+w7YrGlw80Ag4sA86qkfCXRBLmMc4I2US+aPMd4uKvwj5g=="
+    },
     "dayjs": {
       "version": "1.10.7",
       "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
@@ -6716,7 +6767,7 @@
     "decamelize-keys": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
-      "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=",
+      "integrity": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==",
       "dev": true,
       "requires": {
         "decamelize": "^1.1.0",
@@ -6726,7 +6777,7 @@
         "map-obj": {
           "version": "1.0.1",
           "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
-          "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+          "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
           "dev": true
         }
       }
@@ -6982,7 +7033,7 @@
     "delegates": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+      "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
       "dev": true
     },
     "depd": {
@@ -9117,7 +9168,7 @@
     "gauge": {
       "version": "2.7.4",
       "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
-      "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+      "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
       "dev": true,
       "requires": {
         "aproba": "^1.0.3",
@@ -9133,13 +9184,13 @@
         "ansi-regex": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
           "dev": true
         },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
           "dev": true,
           "requires": {
             "ansi-regex": "^2.0.0"
@@ -9186,7 +9237,7 @@
     "get-stdin": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-      "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+      "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==",
       "dev": true
     },
     "get-stream": {
@@ -9417,7 +9468,7 @@
     "har-schema": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+      "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
       "dev": true
     },
     "har-validator": {
@@ -9505,7 +9556,7 @@
     "has-unicode": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+      "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
       "dev": true
     },
     "has-value": {
@@ -10131,7 +10182,7 @@
     "http-signature": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+      "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
       "dev": true,
       "requires": {
         "assert-plus": "^1.0.0",
@@ -10637,7 +10688,7 @@
     "is-fullwidth-code-point": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
-      "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+      "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
       "dev": true,
       "requires": {
         "number-is-nan": "^1.0.0"
@@ -13692,7 +13743,7 @@
         "arrify": {
           "version": "1.0.1",
           "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-          "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+          "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
           "dev": true
         }
       }
@@ -14246,19 +14297,19 @@
         "ansi-regex": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
           "dev": true
         },
         "ansi-styles": {
           "version": "2.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
           "dev": true
         },
         "chalk": {
           "version": "1.1.3",
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
           "dev": true,
           "requires": {
             "ansi-styles": "^2.2.1",
@@ -14271,7 +14322,7 @@
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
           "dev": true,
           "requires": {
             "ansi-regex": "^2.0.0"
@@ -14280,7 +14331,7 @@
         "supports-color": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
           "dev": true
         }
       }
@@ -14408,7 +14459,7 @@
     "number-is-nan": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
-      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==",
       "dev": true
     },
     "nwsapi": {
@@ -16070,6 +16121,14 @@
         "prop-types": "^15.8.1"
       }
     },
+    "react-day-picker": {
+      "version": "7.4.9",
+      "resolved": "https://registry.npmmirror.com/react-day-picker/-/react-day-picker-7.4.9.tgz",
+      "integrity": "sha512-CcXf0p7p6gTYnG0+n/4wNGljZuQDXl4HhgcxsXB0nX+8D4LnRho9EclPA/aLz4WlvvVpfY+AEgj2ylgPj4nm/g==",
+      "requires": {
+        "prop-types": "^15.6.2"
+      }
+    },
     "react-dom": {
       "version": "17.0.2",
       "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
@@ -16933,7 +16992,7 @@
         "is-fullwidth-code-point": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
           "dev": true
         },
         "locate-path": {
@@ -17093,7 +17152,7 @@
     "scss-tokenizer": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
-      "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
+      "integrity": "sha512-dYE8LhncfBUar6POCxMTm0Ln+erjeczqEvCJib5/7XNkdw1FkUGgwMPY360FY0FgPWQxHWCx29Jl3oejyGLM9Q==",
       "dev": true,
       "requires": {
         "js-base64": "^2.1.8",
@@ -17103,7 +17162,7 @@
         "source-map": {
           "version": "0.4.4",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
-          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+          "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==",
           "dev": true,
           "requires": {
             "amdefine": ">=0.0.4"
@@ -18048,7 +18107,7 @@
     "string-width": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-      "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+      "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==",
       "dev": true,
       "requires": {
         "code-point-at": "^1.0.0",
@@ -18059,13 +18118,13 @@
         "ansi-regex": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
           "dev": true
         },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
           "dev": true,
           "requires": {
             "ansi-regex": "^2.0.0"
diff --git a/config-ui/package.json b/config-ui/package.json
index ad443bf1c..af8e215ae 100644
--- a/config-ui/package.json
+++ b/config-ui/package.json
@@ -14,6 +14,7 @@
   "dependencies": {
     "@babel/eslint-parser": "^7.18.2",
     "@blueprintjs/core": "^4.13.0",
+    "@blueprintjs/datetime2": "^0.9.6",
     "@blueprintjs/popover2": "^1.10.2",
     "@blueprintjs/select": "^4.8.12",
     "@emotion/react": "^11.10.4",
diff --git a/config-ui/src/components/blueprints/StartFromSelector.tsx b/config-ui/src/components/blueprints/StartFromSelector.tsx
new file mode 100644
index 000000000..0694da986
--- /dev/null
+++ b/config-ui/src/components/blueprints/StartFromSelector.tsx
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+import React, {useCallback, useEffect, useMemo} from 'react'
+import {Tag} from '@blueprintjs/core'
+import {TimePrecision} from "@blueprintjs/datetime"
+import {DateInput2} from "@blueprintjs/datetime2"
+import dayjs from '@/utils/time'
+
+const StartFromSelector = (
+  {
+    placeholder = 'Select start from',
+    disabled = false,
+    autoFillDefault = false,
+    date,
+    onSave,
+  }: {
+    placeholder?: string,
+    disabled?: boolean,
+    autoFillDefault?: boolean,
+    date: string | null,
+    onSave: (newDate: string | null, isUserChange?: boolean) => void,
+  }) => {
+
+  const formatDate = useCallback((date: Date | string) => dayjs(date).format("YYYY-MM-DD[T]HH:mm:ssZ"), []);
+  const displayDate = useCallback((date: Date) => dayjs(date).format('L LTS'), []);
+  const parseDate = useCallback((str: string) => dayjs(str).toDate(), []);
+  const chooseDate = (date: Date | string | null) => {
+    onSave(date ? formatDate(date) : null)
+  }
+
+  const quickDates = useMemo(() => {
+    const now = new Date()
+    now.setHours(0, 0, 0, 0)
+    const ago6m = new Date(now)
+    ago6m.setMonth(now.getMonth() - 6)
+    const ago90d = new Date(now)
+    ago90d.setDate(ago90d.getDate() - 90)
+    const ago30d = new Date(now)
+    ago30d.setDate(ago30d.getDate() - 30)
+    const ago1y = new Date(now)
+    ago1y.setUTCFullYear(ago1y.getFullYear() - 1)
+    return [
+      {label: 'Last 6 months', date: ago6m},
+      {label: 'Last 90 days', date: ago90d},
+      {label: 'Last 30 days', date: ago30d},
+      {label: 'Last Year', date: ago1y}
+    ]
+  }, [])
+
+  useEffect(() => {
+    if (!date && autoFillDefault) {
+      onSave(formatDate(quickDates[0].date))
+    }
+  }, [date])
+
+  return (
+    <>
+      <div
+        className='start-from'
+      >
+        <div
+          className="123"
+          style={{display: 'flex', marginBottom: '10px'}}>
+          {quickDates.map(quickDate => <Tag
+            key={quickDate.date.toISOString()} minimal={formatDate(quickDate.date) != date}
+            intent="primary"
+            interactive={!disabled}
+            onClick={() => chooseDate(quickDate.date)}
+            style={{marginRight: 5}}>{quickDate.label}
+          </Tag>)}
+        </div>
+
+        <div style={{display: "flex", alignItems: "baseline"}}>
+          <DateInput2
+            disabled={disabled}
+            timePrecision={TimePrecision.MINUTE}
+            formatDate={displayDate}
+            parseDate={parseDate}
+            fill={false}
+            placeholder={placeholder}
+            onChange={chooseDate}
+            popoverProps={{placement: "bottom"}}
+            value={date}
+          />
+          <span style={{fontWeight: 'bold'}}> to Now</span>
+        </div>
+      </div>
+    </>
+  )
+}
+
+export default StartFromSelector
diff --git a/config-ui/src/components/blueprints/create-workflow/DataSync.jsx b/config-ui/src/components/blueprints/create-workflow/DataSync.jsx
index 5dd0bdb8f..669b9c84a 100644
--- a/config-ui/src/components/blueprints/create-workflow/DataSync.jsx
+++ b/config-ui/src/components/blueprints/create-workflow/DataSync.jsx
@@ -36,11 +36,14 @@ import {
 import InputValidationError from '@/components/validation/InputValidationError'
 
 import CronHelp from '@/images/cron-help.png'
+import StartFromSelector from '@/components/blueprints/StartFromSelector'
 
 const DataSync = (props) => {
   const {
     skipOnFail,
     setSkipOnFail,
+    createdDateAfter,
+    setCreatedDateAfter,
     activeStep,
     cronConfig,
     customCronConfig,
@@ -94,6 +97,16 @@ const DataSync = (props) => {
           </>
         )}
 
+        <h4>Time Filter *</h4>
+        <p>
+          Select the data range you wish to collect. DevLake will collect the
+          last six months of data by default.
+        </p>
+        <StartFromSelector
+          date={createdDateAfter}
+          onSave={setCreatedDateAfter}
+        />
+
         <h4>Frequency</h4>
         <p>Blueprints will run recurringly based on the sync frequency.</p>
 
diff --git a/config-ui/src/components/pipelines/StageTaskName.jsx b/config-ui/src/components/pipelines/StageTaskName.jsx
index cd640005f..cc048e568 100644
--- a/config-ui/src/components/pipelines/StageTaskName.jsx
+++ b/config-ui/src/components/pipelines/StageTaskName.jsx
@@ -122,7 +122,9 @@ const StageTaskName = (props) => {
                     <>{ProviderLabels.JENKINS}</>
                   )}
                   {task.plugin === Providers.TAPD && <>{ProviderLabels.TAPD}</>}
-                  {task.plugin === Providers.ZENTAO && <>{ProviderLabels.ZENTAO}</>}
+                  {task.plugin === Providers.ZENTAO && (
+                    <>{ProviderLabels.ZENTAO}</>
+                  )}
                   {task.plugin === Providers.JIRA && (
                     <>Board ID {task.options.boardId}</>
                   )}
diff --git a/config-ui/src/data/BlueprintWorkflow.js b/config-ui/src/data/BlueprintWorkflow.js
index e5edfa138..e6ccbfcb8 100644
--- a/config-ui/src/data/BlueprintWorkflow.js
+++ b/config-ui/src/data/BlueprintWorkflow.js
@@ -47,8 +47,8 @@ const WorkflowSteps = [
   {
     id: 4,
     active: 0,
-    name: 'set-sync-frequeny',
-    title: 'Set Sync Frequency',
+    name: 'set-sync-policy',
+    title: 'Set Sync Policy',
     complete: false,
     icon: null,
     errors: []
@@ -77,8 +77,8 @@ const WorkflowAdvancedSteps = [
   {
     id: 2,
     active: 0,
-    name: 'set-sync-frequeny',
-    title: 'Set Sync Frequency',
+    name: 'set-sync-policy',
+    title: 'Set Sync Policy',
     complete: false,
     icon: null,
     errors: []
diff --git a/config-ui/src/data/availablePlugins.js b/config-ui/src/data/availablePlugins.js
index dc5f79d2d..4d6d25c6d 100644
--- a/config-ui/src/data/availablePlugins.js
+++ b/config-ui/src/data/availablePlugins.js
@@ -15,6 +15,13 @@
  * limitations under the License.
  *
  */
-const AVAILABLE_PLUGINS = ['gitlab', 'jira', 'jenkins', 'github', 'tapd', 'zentao']
+const AVAILABLE_PLUGINS = [
+  'gitlab',
+  'jira',
+  'jenkins',
+  'github',
+  'tapd',
+  'zentao'
+]
 
 module.exports = AVAILABLE_PLUGINS
diff --git a/config-ui/src/data/pipeline-config-samples/jira.js b/config-ui/src/data/pipeline-config-samples/jira.js
index bb7a6ea2f..11ab0b3ef 100644
--- a/config-ui/src/data/pipeline-config-samples/jira.js
+++ b/config-ui/src/data/pipeline-config-samples/jira.js
@@ -22,7 +22,7 @@ const jiraConfig = [
       options: {
         connectionId: 1,
         boardId: 8,
-        since: '2006-01-02T15:04:05Z'
+        createdDateAfter: '2006-01-02T15:04:05Z'
       }
     }
   ]
diff --git a/config-ui/src/data/pipeline-config-samples/zentao.js b/config-ui/src/data/pipeline-config-samples/zentao.js
index 22590ee72..4eeccfd31 100644
--- a/config-ui/src/data/pipeline-config-samples/zentao.js
+++ b/config-ui/src/data/pipeline-config-samples/zentao.js
@@ -23,7 +23,7 @@ const zentaoConfig = [
         connectionId: 1,
         productId: 1,
         projectId: 1,
-        executionId: 1,
+        executionId: 1
       }
     }
   ]
diff --git a/config-ui/src/hooks/useBlueprintManager.jsx b/config-ui/src/hooks/useBlueprintManager.jsx
index 0916af291..4246d8f0b 100644
--- a/config-ui/src/hooks/useBlueprintManager.jsx
+++ b/config-ui/src/hooks/useBlueprintManager.jsx
@@ -15,14 +15,14 @@
  * limitations under the License.
  *
  */
-import { useCallback, useEffect, useState } from 'react'
-import { DEVLAKE_ENDPOINT } from '@/utils/config'
+import {useCallback, useState} from 'react'
+import {DEVLAKE_ENDPOINT} from '@/utils/config'
 import request from '@/utils/request'
-import { ToastNotification } from '@/components/Toast'
-import { NullBlueprint, BlueprintMode } from '@/data/NullBlueprint'
+import {ToastNotification} from '@/components/Toast'
+import {BlueprintMode, NullBlueprint} from '@/data/NullBlueprint'
 import cron from 'cron-validate'
 import parser from 'cron-parser'
-import { Intent } from '@blueprintjs/core'
+import {Intent} from '@blueprintjs/core'
 
 function useBlueprintManager(
   blueprintName = `BLUEPRINT WEEKLY ${Date.now()}`,
@@ -42,7 +42,8 @@ function useBlueprintManager(
   const [interval, setInterval] = useState('daily')
   const [tasks, setTasks] = useState([])
   const [settings, setSettings] = useState({
-    version: '1.0.0',
+    version: '2.0.0',
+    createdDateAfter: null,
     connections: []
   })
   const [mode, setMode] = useState(BlueprintMode.NORMAL)
@@ -50,6 +51,7 @@ function useBlueprintManager(
   const [detectedProviderTasks, setDetectedProviderTasks] = useState([])
   const [isManual, setIsManual] = useState(false)
   const [skipOnFail, setSkipOnFail] = useState(false)
+  const [createdDateAfter, setCreatedDateAfter] = useState(null)
   const [rawConfiguration, setRawConfiguration] = useState(
     JSON.stringify([tasks], null, '  ')
   )
@@ -192,6 +194,7 @@ function useBlueprintManager(
               : NullBlueprint
           )
           setSkipOnFail(blueprintData.skipOnFail)
+          setCreatedDateAfter(blueprintData.settings.createdDateAfter)
           setErrors(b.status !== 200 ? [b.data] : [])
           setTimeout(() => {
             setIsFetching(false)
@@ -236,11 +239,12 @@ function useBlueprintManager(
           cronConfig: detectCronConfig(),
           // @todo: refactor tasks ===> plan at higher levels
           plan: tasks,
-          settings,
+          // because of forthcoming refactor, just set here temporarily
+          settings: { createdDateAfter, ...settings },
           enable: enable,
           mode,
           isManual,
-          skipOnFail
+          skipOnFail,
         }
         console.log('>> DISPATCHING BLUEPRINT SAVE REQUEST', blueprintPayload)
         const run = async () => {
@@ -303,6 +307,7 @@ function useBlueprintManager(
       enable,
       isManual,
       skipOnFail,
+      createdDateAfter,
       detectCronInterval
     ]
   )
@@ -564,6 +569,8 @@ function useBlueprintManager(
     isManual,
     skipOnFail,
     setSkipOnFail,
+    createdDateAfter,
+    setCreatedDateAfter,
     errors
   }
 }
diff --git a/config-ui/src/hooks/useDataScopesManager.jsx b/config-ui/src/hooks/useDataScopesManager.jsx
index 28f065e7f..2b11384d5 100644
--- a/config-ui/src/hooks/useDataScopesManager.jsx
+++ b/config-ui/src/hooks/useDataScopesManager.jsx
@@ -421,7 +421,7 @@ function useDataScopesManager({
           (pC) => pC.connectionId === c.connectionId && pC.plugin === c.plugin
         )?.name ||
         `${ProviderLabels[c.plugin?.toUpperCase()]} #${c.connectionId || cIdx}`,
-      // FIXME: entities in `c.scope[0]?.entities` means one of ALL_DATA_DOMAINS and is saved in db,
+      // FIXME: entities in `c.scopes[0]?.entities` means one of ALL_DATA_DOMAINS and is saved in db,
       // So it kept here.
       dataDomains: c.scopes[0]?.entities?.map((e) =>
         ALL_DATA_DOMAINS.find((de) => de.value === e)
diff --git a/config-ui/src/hooks/usePipelineManager.jsx b/config-ui/src/hooks/usePipelineManager.jsx
index fdbd7647e..f475f44e9 100644
--- a/config-ui/src/hooks/usePipelineManager.jsx
+++ b/config-ui/src/hooks/usePipelineManager.jsx
@@ -179,41 +179,48 @@ function usePipelineManager(
     }
   }, [])
 
-  const fetchAllPipelines = useCallback((blueprintId, status = null, fetchTimeout = 500) => {
-    try {
-      setIsFetchingAll(true)
-      setErrors([])
-      ToastNotification.clear()
-      console.log('>> FETCHING ALL PIPELINE RUNS...')
-      const fetchAll = async () => {
-        let queryParams = '?blueprint_id=' + blueprintId
-        queryParams +=
-          status &&
-          ['TASK_COMPLETED', 'TASK_RUNNING', 'TASK_FAILED'].includes(status)
-            ? `&status=${status}&`
-            : ''
-        const p = await request.get(
-          `${DEVLAKE_ENDPOINT}/pipelines${queryParams}`
-        )
-        console.log('>> RAW PIPELINES RUN DATA FROM API...', p.data?.pipelines)
-        let pipelines = p.data && p.data.pipelines ? [...p.data.pipelines] : []
-        // @todo: remove "ID" fallback key when no longer needed
-        pipelines = pipelines.map((p) => ({ ...p, ID: p.id }))
-        setPipelines(pipelines)
-        setPipelineCount(p.data ? p.data.count : 0)
-        setTimeout(() => {
-          setIsFetchingAll(false)
-        }, fetchTimeout)
+  const fetchAllPipelines = useCallback(
+    (blueprintId, status = null, fetchTimeout = 500) => {
+      try {
+        setIsFetchingAll(true)
+        setErrors([])
+        ToastNotification.clear()
+        console.log('>> FETCHING ALL PIPELINE RUNS...')
+        const fetchAll = async () => {
+          let queryParams = '?blueprint_id=' + blueprintId
+          queryParams +=
+            status &&
+            ['TASK_COMPLETED', 'TASK_RUNNING', 'TASK_FAILED'].includes(status)
+              ? `&status=${status}&`
+              : ''
+          const p = await request.get(
+            `${DEVLAKE_ENDPOINT}/pipelines${queryParams}`
+          )
+          console.log(
+            '>> RAW PIPELINES RUN DATA FROM API...',
+            p.data?.pipelines
+          )
+          let pipelines =
+            p.data && p.data.pipelines ? [...p.data.pipelines] : []
+          // @todo: remove "ID" fallback key when no longer needed
+          pipelines = pipelines.map((p) => ({ ...p, ID: p.id }))
+          setPipelines(pipelines)
+          setPipelineCount(p.data ? p.data.count : 0)
+          setTimeout(() => {
+            setIsFetchingAll(false)
+          }, fetchTimeout)
+        }
+        fetchAll()
+      } catch (e) {
+        setIsFetchingAll(false)
+        setErrors([e.message])
+        setPipelines([])
+        setPipelineCount(0)
+        console.log('>> FAILED TO FETCH ALL PIPELINE RUNS!!', e)
       }
-      fetchAll()
-    } catch (e) {
-      setIsFetchingAll(false)
-      setErrors([e.message])
-      setPipelines([])
-      setPipelineCount(0)
-      console.log('>> FAILED TO FETCH ALL PIPELINE RUNS!!', e)
-    }
-  }, [])
+    },
+    []
+  )
 
   const buildPipelineStages = useCallback((tasks = [], outputArray = false) => {
     let stages = {}
diff --git a/config-ui/src/index.css b/config-ui/src/index.css
index c42a38d70..fb1a71a35 100644
--- a/config-ui/src/index.css
+++ b/config-ui/src/index.css
@@ -21,3 +21,4 @@
 @import '~@blueprintjs/icons/lib/css/blueprint-icons.css';
 @import '~@blueprintjs/select/lib/css/blueprint-select.css';
 @import '~@blueprintjs/popover2/lib/css/blueprint-popover2.css';
+@import '~@blueprintjs/datetime/lib/css/blueprint-datetime.css';
diff --git a/config-ui/src/pages/blueprint/create/components/workflow/index.tsx b/config-ui/src/pages/blueprint/create/components/workflow/index.tsx
index c05ad99ea..0767cc72b 100644
--- a/config-ui/src/pages/blueprint/create/components/workflow/index.tsx
+++ b/config-ui/src/pages/blueprint/create/components/workflow/index.tsx
@@ -33,9 +33,9 @@ export const WorkFlow = () => {
             'Add Data Connections',
             'Set Data Scope',
             'Add Transformation (Optional)',
-            'Set Sync Frequency'
+            'Set Sync Policy'
           ]
-        : ['Create Advanced Configuration', 'Set Sync Frequency'],
+        : ['Create Advanced Configuration', 'Set Sync Policy'],
     [mode]
   )
 
diff --git a/config-ui/src/pages/blueprint/create/hooks/blueprint-context.ts b/config-ui/src/pages/blueprint/create/hooks/blueprint-context.ts
index 6544a594b..43654cbe2 100644
--- a/config-ui/src/pages/blueprint/create/hooks/blueprint-context.ts
+++ b/config-ui/src/pages/blueprint/create/hooks/blueprint-context.ts
@@ -36,6 +36,7 @@ export type BlueprintContextType = {
   cronConfig: string
   isManual: boolean
   skipOnFail: boolean
+  createdDateAfter: string | null
 
   onChangeStep: React.Dispatch<React.SetStateAction<number>>
   onChangeShowInspector: React.Dispatch<React.SetStateAction<boolean>>
@@ -51,6 +52,7 @@ export type BlueprintContextType = {
   onChangeCronConfig: React.Dispatch<React.SetStateAction<string>>
   onChangeIsManual: React.Dispatch<React.SetStateAction<boolean>>
   onChangeSkipOnFail: React.Dispatch<React.SetStateAction<boolean>>
+  onChangeCreatedDateAfter: React.Dispatch<React.SetStateAction<string | null>>
 
   onSave: () => void
   onSaveAndRun: () => void
@@ -71,6 +73,7 @@ export const BlueprintContext = React.createContext<BlueprintContextType>({
   cronConfig: '0 0 * * *',
   isManual: false,
   skipOnFail: false,
+  createdDateAfter: null,
 
   onChangeStep: () => {},
   onChangeShowInspector: () => {},
@@ -84,6 +87,7 @@ export const BlueprintContext = React.createContext<BlueprintContextType>({
   onChangeCronConfig: () => {},
   onChangeIsManual: () => {},
   onChangeSkipOnFail: () => {},
+  onChangeCreatedDateAfter: () => {},
 
   onSave: () => {},
   onSaveAndRun: () => {}
diff --git a/config-ui/src/pages/blueprint/create/hooks/use-blueprint-value.ts b/config-ui/src/pages/blueprint/create/hooks/use-blueprint-value.ts
index ad27b4f05..495511936 100644
--- a/config-ui/src/pages/blueprint/create/hooks/use-blueprint-value.ts
+++ b/config-ui/src/pages/blueprint/create/hooks/use-blueprint-value.ts
@@ -45,6 +45,7 @@ export const useBlueprintValue = ({ from, projectName }: Props) => {
   const [cronConfig, setCronConfig] = useState('0 0 * * *')
   const [isManual, setIsManual] = useState(false)
   const [skipOnFail, setSkipOnFail] = useState(false)
+  const [createdDateAfter, setCreatedDateAfter] = useState<string | null>(null)
 
   const history = useHistory()
 
@@ -85,7 +86,8 @@ export const useBlueprintValue = ({ from, projectName }: Props) => {
       enable: true,
       cronConfig,
       isManual,
-      skipOnFail
+      skipOnFail,
+      createdDateAfter
     }
 
     if (mode === ModeEnum.normal) {
@@ -115,6 +117,7 @@ export const useBlueprintValue = ({ from, projectName }: Props) => {
     cronConfig,
     isManual,
     skipOnFail,
+    createdDateAfter,
     connections,
     scope
   ])
@@ -146,6 +149,7 @@ export const useBlueprintValue = ({ from, projectName }: Props) => {
       cronConfig,
       isManual,
       skipOnFail,
+      createdDateAfter,
 
       onChangeStep: setStep,
       onChangeShowInspector: setShowInspector,
@@ -159,6 +163,7 @@ export const useBlueprintValue = ({ from, projectName }: Props) => {
       onChangeCronConfig: setCronConfig,
       onChangeIsManual: setIsManual,
       onChangeSkipOnFail: setSkipOnFail,
+      onChangeCreatedDateAfter: setCreatedDateAfter,
 
       onSave: handleSave,
       onSaveAndRun: hanldeSaveAndRun
@@ -176,7 +181,8 @@ export const useBlueprintValue = ({ from, projectName }: Props) => {
       scope,
       cronConfig,
       isManual,
-      skipOnFail
+      skipOnFail,
+      createdDateAfter
     ]
   )
 }
diff --git a/config-ui/src/pages/blueprint/create/step-four/index.tsx b/config-ui/src/pages/blueprint/create/step-four/index.tsx
index deba653fc..cd3c42c1a 100644
--- a/config-ui/src/pages/blueprint/create/step-four/index.tsx
+++ b/config-ui/src/pages/blueprint/create/step-four/index.tsx
@@ -33,6 +33,7 @@ import CronHelp from '@/images/cron-help.png'
 import { useBlueprint } from '../hooks'
 
 import * as S from './styled'
+import StartFromSelector from "@/components/blueprints/StartFromSelector";
 
 const cronPresets = [
   {
@@ -64,9 +65,11 @@ export const StepFour = () => {
     cronConfig,
     isManual,
     skipOnFail,
+    createdDateAfter,
     onChangeCronConfig,
     onChangeIsManual,
-    onChangeSkipOnFail
+    onChangeSkipOnFail,
+    onChangeCreatedDateAfter
   } = useBlueprint()
 
   const description = useMemo(() => {
@@ -108,12 +111,21 @@ export const StepFour = () => {
 
   return (
     <S.Card>
-      <h2>Set Sync Frequency</h2>
-      <p style={{ margin: '10px 0' }}>{description}</p>
+      <h2>Set Sync Policy</h2>
       <Divider />
+      <div className='block'>
+          <h4>Time Filter *</h4>
+          <p>Select the data range you wish to collect. DevLake will collect the last six months of data by default.</p>
+          <StartFromSelector
+            autoFillDefault={true}
+            date={createdDateAfter}
+            onSave={onChangeCreatedDateAfter}
+          />
+      </div>
       <div className='block'>
         <h3>Frequency</h3>
         <p>Blueprints will run recurringly based on the sync frequency.</p>
+        <p style={{ margin: '10px 0' }}>{description}</p>
         <RadioGroup selectedValue={frequency} onChange={handleChangeFrequency}>
           <Radio label='Manual' value='manual' />
           {cronPresets.map((cron) => (
diff --git a/config-ui/src/pages/blueprint/create/step-one/example/jira.ts b/config-ui/src/pages/blueprint/create/step-one/example/jira.ts
index c88de738a..a99aa7cf4 100644
--- a/config-ui/src/pages/blueprint/create/step-one/example/jira.ts
+++ b/config-ui/src/pages/blueprint/create/step-one/example/jira.ts
@@ -23,7 +23,7 @@ export default [
       options: {
         connectionId: 1,
         boardId: 8,
-        since: '2006-01-02T15:04:05Z'
+        createdDateAfter: '2006-01-02T15:04:05Z'
       }
     }
   ]
diff --git a/config-ui/src/pages/blueprints/blueprint-settings.jsx b/config-ui/src/pages/blueprints/blueprint-settings.jsx
index a69331d62..ca32ffa97 100644
--- a/config-ui/src/pages/blueprints/blueprint-settings.jsx
+++ b/config-ui/src/pages/blueprints/blueprint-settings.jsx
@@ -155,7 +155,9 @@ const BlueprintSettings = ({ id }) => {
     saveComplete,
     errors: blueprintErrors,
     skipOnFail,
-    setSkipOnFail
+    setSkipOnFail,
+    createdDateAfter,
+    setCreatedDateAfter
   } = useBlueprintManager()
 
   const {
@@ -422,7 +424,7 @@ const BlueprintSettings = ({ id }) => {
           title = 'Change Blueprint Name'
           break
         case 'cronConfig':
-          title = 'Change Sync Frequency'
+          title = 'Change Sync Policy'
           break
         case 'plan':
           title = 'Change Task Configuration'
@@ -678,6 +680,7 @@ const BlueprintSettings = ({ id }) => {
           payload: {
             isManual: !!isManualCron,
             skipOnFail,
+            settings: {...blueprintSettings, createdDateAfter},
             cronConfig: isManualCron
               ? getCronPreset('daily').cronConfig
               : isCustomCron
@@ -707,6 +710,7 @@ const BlueprintSettings = ({ id }) => {
     }
   }, [
     skipOnFail,
+    createdDateAfter,
     blueprintName,
     cronConfig,
     customCronConfig,
@@ -877,7 +881,7 @@ const BlueprintSettings = ({ id }) => {
                 className='configure-settings-frequency'
                 style={{ marginLeft: '40px' }}
               >
-                <h3>Sync Frequency</h3>
+                <h3>Sync Policy</h3>
                 <div style={{ display: 'flex', alignItems: 'center' }}>
                   <div className='blueprint-frequency'>
                     {activeBlueprint?.isManual ? (
@@ -1023,6 +1027,8 @@ const BlueprintSettings = ({ id }) => {
                 <DataSync
                   skipOnFail={skipOnFail}
                   setSkipOnFail={setSkipOnFail}
+                  createdDateAfter={createdDateAfter}
+                  setCreatedDateAfter={setCreatedDateAfter}
                   cronConfig={cronConfig}
                   customCronConfig={customCronConfig}
                   createCron={createCron}
diff --git a/models/blueprint.go b/models/blueprint.go
index f223330ff..6d948687e 100644
--- a/models/blueprint.go
+++ b/models/blueprint.go
@@ -48,11 +48,11 @@ type Blueprint struct {
 }
 
 type BlueprintSettings struct {
-	Version     string          `json:"version" validate:"required,semver,oneof=1.0.0"`
-	SkipOnFail  bool            `json:"skipOnFail"`
-	Connections json.RawMessage `json:"connections" validate:"required"`
-	BeforePlan  json.RawMessage `json:"before_plan"`
-	AfterPlan   json.RawMessage `json:"after_plan"`
+	Version          string          `json:"version" validate:"required,semver,oneof=1.0.0"`
+	CreatedDateAfter *time.Time      `json:"createdDateAfter"`
+	Connections      json.RawMessage `json:"connections" validate:"required"`
+	BeforePlan       json.RawMessage `json:"before_plan"`
+	AfterPlan        json.RawMessage `json:"after_plan"`
 }
 
 // UnmarshalPlan unmarshals Plan in JSON to strong-typed core.PipelinePlan
diff --git a/models/migrationscripts/20221107_add_skip_on_fail.go b/models/migrationscripts/20221107_add_skip_on_fail.go
index 71942ea55..acf12b817 100644
--- a/models/migrationscripts/20221107_add_skip_on_fail.go
+++ b/models/migrationscripts/20221107_add_skip_on_fail.go
@@ -33,12 +33,12 @@ func (p blueprint20221107) TableName() string {
 	return "_devlake_blueprints"
 }
 
-type task20221107 struct {
+type pipeline20221107 struct {
 	SkipOnFail bool
 }
 
-func (t task20221107) TableName() string {
-	return "_devlake_tasks"
+func (t pipeline20221107) TableName() string {
+	return "_devlake_pipelines"
 }
 
 type addSkipOnFail struct{}
@@ -47,7 +47,7 @@ func (*addSkipOnFail) Up(basicRes core.BasicRes) errors.Error {
 	return migrationhelper.AutoMigrateTables(
 		basicRes,
 		&blueprint20221107{},
-		&task20221107{},
+		&pipeline20221107{},
 	)
 }
 
@@ -56,5 +56,5 @@ func (*addSkipOnFail) Version() uint64 {
 }
 
 func (*addSkipOnFail) Name() string {
-	return "add skip_on_fail to _devlake_pipelines and _devlake_tasks"
+	return "add skip_on_fail to _devlake_pipelines and _devlake_blueprint"
 }
diff --git a/models/pipeline.go b/models/pipeline.go
index 7427c2338..97fba77e4 100644
--- a/models/pipeline.go
+++ b/models/pipeline.go
@@ -40,6 +40,7 @@ type Pipeline struct {
 	SpentSeconds  int            `json:"spentSeconds"`
 	Stage         int            `json:"stage"`
 	Labels        []string       `json:"labels"`
+	SkipOnFail    bool           `json:"skipOnFail"`
 }
 
 // We use a 2D array because the request body must be an array of a set of tasks
@@ -48,6 +49,7 @@ type NewPipeline struct {
 	Name        string            `json:"name"`
 	Plan        core.PipelinePlan `json:"plan" swaggertype:"array,string" example:"please check api /pipelines/<PLUGIN_NAME>/pipeline-plan"`
 	Labels      []string          `json:"labels"`
+	SkipOnFail  bool              `json:"skipOnFail"`
 	BlueprintId uint64
 }
 
@@ -64,6 +66,7 @@ type DbPipeline struct {
 	Message       string     `json:"message"`
 	SpentSeconds  int        `json:"spentSeconds"`
 	Stage         int        `json:"stage"`
+	SkipOnFail    bool       `json:"skipOnFail"`
 
 	Labels []DbPipelineLabel `json:"-" gorm:"-"`
 }
diff --git a/models/task.go b/models/task.go
index 2d07801d0..0dd571a04 100644
--- a/models/task.go
+++ b/models/task.go
@@ -62,7 +62,6 @@ type Task struct {
 	BeganAt       *time.Time `json:"beganAt"`
 	FinishedAt    *time.Time `json:"finishedAt" gorm:"index"`
 	SpentSeconds  int        `json:"spentSeconds"`
-	SkipOnFail    bool       `json:"-"`
 }
 
 type NewTask struct {
diff --git a/plugins/core/plugin_blueprint.go b/plugins/core/plugin_blueprint.go
index 1226a488a..11b2e6962 100644
--- a/plugins/core/plugin_blueprint.go
+++ b/plugins/core/plugin_blueprint.go
@@ -20,15 +20,15 @@ package core
 import (
 	"encoding/json"
 	"github.com/apache/incubator-devlake/errors"
+	"time"
 )
 
 // PipelineTask represents a smallest unit of execution inside a PipelinePlan
 type PipelineTask struct {
 	// Plugin name
-	Plugin     string                 `json:"plugin" binding:"required"`
-	SkipOnFail bool                   `json:"skipOnFail"`
-	Subtasks   []string               `json:"subtasks"`
-	Options    map[string]interface{} `json:"options"`
+	Plugin   string                 `json:"plugin" binding:"required"`
+	Subtasks []string               `json:"subtasks"`
+	Options  map[string]interface{} `json:"options"`
 }
 
 // PipelineStage consist of multiple PipelineTasks, they will be executed in parallel
@@ -120,7 +120,11 @@ type Scope interface {
 // Project, so that complex metrics like DORA can be implemented based on a set
 // of Data Scopes
 type DataSourcePluginBlueprintV200 interface {
-	MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*BlueprintScopeV200) (PipelinePlan, []Scope, errors.Error)
+	MakeDataSourcePipelinePlanV200(
+		connectionId uint64,
+		scopes []*BlueprintScopeV200,
+		syncPolicy BlueprintSyncPolicy,
+	) (PipelinePlan, []Scope, errors.Error)
 }
 
 // BlueprintConnectionV200 contains the pluginName/connectionId  and related Scopes,
@@ -166,3 +170,9 @@ type CompositePluginBlueprintV200 interface {
 	DataSourcePluginBlueprintV200
 	MetricPluginBlueprintV200
 }
+
+type BlueprintSyncPolicy struct {
+	Version          string     `json:"version" validate:"required,semver,oneof=1.0.0"`
+	SkipOnFail       bool       `json:"skipOnFail"`
+	CreatedDateAfter *time.Time `json:"createdDateAfter"`
+}
diff --git a/plugins/dora/impl/impl.go b/plugins/dora/impl/impl.go
index 1bcb3168a..ca5a8f203 100644
--- a/plugins/dora/impl/impl.go
+++ b/plugins/dora/impl/impl.go
@@ -19,7 +19,6 @@ package impl
 
 import (
 	"encoding/json"
-	"fmt"
 	"github.com/apache/incubator-devlake/errors"
 	"github.com/apache/incubator-devlake/plugins/core"
 	"github.com/apache/incubator-devlake/plugins/dora/models/migrationscripts"
@@ -34,7 +33,6 @@ var _ core.PluginInit = (*Dora)(nil)
 var _ core.PluginTask = (*Dora)(nil)
 var _ core.PluginModel = (*Dora)(nil)
 var _ core.PluginMetric = (*Dora)(nil)
-var _ core.CloseablePluginTask = (*Dora)(nil)
 var _ core.PluginMigration = (*Dora)(nil)
 var _ core.MetricPluginBlueprintV200 = (*Dora)(nil)
 
@@ -143,13 +141,3 @@ func (plugin Dora) MakeMetricPluginPipelinePlanV200(projectName string, options
 
 	return plan, nil
 }
-
-func (plugin Dora) Close(taskCtx core.TaskContext) errors.Error {
-	data, ok := taskCtx.GetData().(*tasks.DoraTaskData)
-	if !ok {
-		return errors.Default.New(fmt.Sprintf("GetData failed when try to close %+v", taskCtx))
-	}
-	// TODO
-	println(data)
-	return nil
-}
diff --git a/plugins/github/api/blueprint_V200_test.go b/plugins/github/api/blueprint_V200_test.go
index 9bc756e7a..07e3b3198 100644
--- a/plugins/github/api/blueprint_V200_test.go
+++ b/plugins/github/api/blueprint_V200_test.go
@@ -77,9 +77,10 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 	}
 	bpScopes := make([]*core.BlueprintScopeV200, 0)
 	bpScopes = append(bpScopes, bs)
+	syncPolicy := &core.BlueprintSyncPolicy{}
 
 	plan := make(core.PipelinePlan, len(bpScopes))
-	plan, err = makeDataSourcePipelinePlanV200(nil, plan, bpScopes, connection, mockApiCLient)
+	plan, err = makeDataSourcePipelinePlanV200(nil, plan, bpScopes, connection, mockApiCLient, syncPolicy)
 	assert.Nil(t, err)
 	basicRes = NewMockBasicRes()
 	scopes, err := makeScopesV200(bpScopes, connection)
@@ -88,17 +89,15 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 	expectPlan := core.PipelinePlan{
 		core.PipelineStage{
 			{
-				Plugin:     "github",
-				Subtasks:   []string{},
-				SkipOnFail: false,
+				Plugin:   "github",
+				Subtasks: []string{},
 				Options: map[string]interface{}{
 					"connectionId": uint64(1),
 					"scopeId":      "1",
 				},
 			},
 			{
-				Plugin:     "gitextractor",
-				SkipOnFail: false,
+				Plugin: "gitextractor",
 				Options: map[string]interface{}{
 					"proxy":  "",
 					"repoId": "github:GithubRepo:1:12345",
@@ -108,8 +107,7 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 		},
 		core.PipelineStage{
 			{
-				Plugin:     "refdiff",
-				SkipOnFail: false,
+				Plugin: "refdiff",
 				Options: map[string]interface{}{
 					"tagsLimit":   10,
 					"tagsOrder":   "reverse semver",
diff --git a/plugins/github/api/blueprint_v200.go b/plugins/github/api/blueprint_v200.go
index d2c7fd1bf..71e8e25a5 100644
--- a/plugins/github/api/blueprint_v200.go
+++ b/plugins/github/api/blueprint_v200.go
@@ -40,7 +40,7 @@ import (
 	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
-func MakeDataSourcePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64, bpScopes []*core.BlueprintScopeV200) (core.PipelinePlan, []core.Scope, errors.Error) {
+func MakeDataSourcePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64, bpScopes []*core.BlueprintScopeV200, syncPolicy *core.BlueprintSyncPolicy) (core.PipelinePlan, []core.Scope, errors.Error) {
 	connectionHelper := helper.NewConnectionHelper(basicRes, validator.New())
 	// get the connection info for url
 	connection := &models.GithubConnection{}
@@ -65,7 +65,7 @@ func MakeDataSourcePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionI
 	}
 
 	plan := make(core.PipelinePlan, len(bpScopes))
-	plan, err = makeDataSourcePipelinePlanV200(subtaskMetas, plan, bpScopes, connection, apiClient)
+	plan, err = makeDataSourcePipelinePlanV200(subtaskMetas, plan, bpScopes, connection, apiClient, syncPolicy)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -83,6 +83,7 @@ func makeDataSourcePipelinePlanV200(
 	bpScopes []*core.BlueprintScopeV200,
 	connection *models.GithubConnection,
 	apiClient helper.ApiClientGetter,
+	syncPolicy *core.BlueprintSyncPolicy,
 ) (core.PipelinePlan, errors.Error) {
 	var err errors.Error
 	var repoRes *tasks.GithubApiRepo
@@ -128,6 +129,9 @@ func makeDataSourcePipelinePlanV200(
 			ConnectionId: githubRepo.ConnectionId,
 			ScopeId:      bpScope.Id,
 		}
+		if syncPolicy.CreatedDateAfter != nil {
+			op.CreatedDateAfter = syncPolicy.CreatedDateAfter.Format(time.RFC3339)
+		}
 		options, err := tasks.EncodeTaskOptions(op)
 		if err != nil {
 			return nil, err
diff --git a/plugins/github/impl/impl.go b/plugins/github/impl/impl.go
index a72b8ee01..cc0408472 100644
--- a/plugins/github/impl/impl.go
+++ b/plugins/github/impl/impl.go
@@ -19,7 +19,6 @@ package impl
 
 import (
 	"fmt"
-	"github.com/apache/incubator-devlake/plugins/github_graphql/impl"
 	"time"
 
 	"github.com/apache/incubator-devlake/errors"
@@ -28,6 +27,7 @@ import (
 	"github.com/apache/incubator-devlake/plugins/github/models"
 	"github.com/apache/incubator-devlake/plugins/github/models/migrationscripts"
 	"github.com/apache/incubator-devlake/plugins/github/tasks"
+	"github.com/apache/incubator-devlake/plugins/github_graphql/impl"
 	"github.com/apache/incubator-devlake/plugins/helper"
 	"github.com/spf13/viper"
 	"gorm.io/gorm"
@@ -164,7 +164,7 @@ func (plugin Github) PrepareTaskData(taskCtx core.TaskContext, options map[strin
 
 	var createdDateAfter time.Time
 	if op.CreatedDateAfter != "" {
-		createdDateAfter, err = errors.Convert01(time.Parse("2006-01-02T15:04:05Z", op.CreatedDateAfter))
+		createdDateAfter, err = errors.Convert01(time.Parse(time.RFC3339, op.CreatedDateAfter))
 		if err != nil {
 			return nil, errors.BadInput.Wrap(err, "invalid value for `createdDateAfter`")
 		}
@@ -234,8 +234,8 @@ func (plugin Github) MakePipelinePlan(connectionId uint64, scope []*core.Bluepri
 	return api.MakePipelinePlan(plugin.SubTaskMetas(), connectionId, scope)
 }
 
-func (plugin Github) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*core.BlueprintScopeV200) (pp core.PipelinePlan, sc []core.Scope, err errors.Error) {
-	return api.MakeDataSourcePipelinePlanV200(plugin.SubTaskMetas(), connectionId, scopes)
+func (plugin Github) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*core.BlueprintScopeV200, syncPolicy core.BlueprintSyncPolicy) (pp core.PipelinePlan, sc []core.Scope, err errors.Error) {
+	return api.MakeDataSourcePipelinePlanV200(plugin.SubTaskMetas(), connectionId, scopes, &syncPolicy)
 }
 
 func (plugin Github) Close(taskCtx core.TaskContext) errors.Error {
diff --git a/plugins/github/tasks/cicd_run_collector.go b/plugins/github/tasks/cicd_run_collector.go
index d614c5a36..713f5e5b6 100644
--- a/plugins/github/tasks/cicd_run_collector.go
+++ b/plugins/github/tasks/cicd_run_collector.go
@@ -23,6 +23,7 @@ import (
 	"github.com/apache/incubator-devlake/errors"
 	"net/http"
 	"net/url"
+	"time"
 
 	"github.com/apache/incubator-devlake/plugins/core"
 	"github.com/apache/incubator-devlake/plugins/helper"
@@ -58,7 +59,7 @@ func CollectRuns(taskCtx core.SubTaskContext) errors.Error {
 		Query: func(reqData *helper.RequestData) (url.Values, errors.Error) {
 			query := url.Values{}
 			if data.CreatedDateAfter != nil {
-				query.Set("created", fmt.Sprintf(">%s", data.CreatedDateAfter.String()))
+				query.Set("created", fmt.Sprintf(">%s", data.CreatedDateAfter.Format(time.RFC3339)))
 			}
 			query.Set("page", fmt.Sprintf("%v", reqData.Pager.Page))
 			query.Set("per_page", fmt.Sprintf("%v", reqData.Pager.Size))
diff --git a/plugins/github_graphql/impl/impl.go b/plugins/github_graphql/impl/impl.go
index 1b662e353..e58a8a6bd 100644
--- a/plugins/github_graphql/impl/impl.go
+++ b/plugins/github_graphql/impl/impl.go
@@ -153,7 +153,7 @@ func (plugin GithubGraphql) PrepareTaskData(taskCtx core.TaskContext, options ma
 	}
 	var createdDateAfter time.Time
 	if op.CreatedDateAfter != "" {
-		createdDateAfter, err = errors.Convert01(time.Parse("2006-01-02T15:04:05Z", op.CreatedDateAfter))
+		createdDateAfter, err = errors.Convert01(time.Parse(time.RFC3339, op.CreatedDateAfter))
 		if err != nil {
 			return nil, errors.BadInput.Wrap(err, "invalid value for `createdDateAfter`")
 		}
diff --git a/plugins/gitlab/api/blueprint_V200_test.go b/plugins/gitlab/api/blueprint_V200_test.go
index dcbdbf615..1a8a5b5d8 100644
--- a/plugins/gitlab/api/blueprint_V200_test.go
+++ b/plugins/gitlab/api/blueprint_V200_test.go
@@ -49,6 +49,7 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 	const testTransformationRuleName string = "github transformation rule"
 	const testProxy string = ""
 
+	syncPolicy := &core.BlueprintSyncPolicy{}
 	bpScopes := []*core.BlueprintScopeV200{
 		{
 			Entities: []string{core.DOMAIN_TYPE_CODE, core.DOMAIN_TYPE_TICKET, core.DOMAIN_TYPE_CICD},
@@ -126,16 +127,13 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 					tasks.CollectApiPipelinesMeta.Name,
 					tasks.ExtractApiPipelinesMeta.Name,
 				},
-				SkipOnFail: false,
 				Options: map[string]interface{}{
 					"connectionId": uint64(1),
 					"projectId":    testID,
-					"entities":     bpScopes[0].Entities,
 				},
 			},
 			{
-				Plugin:     "gitextractor",
-				SkipOnFail: false,
+				Plugin: "gitextractor",
 				Options: map[string]interface{}{
 					"proxy":  "",
 					"repoId": expectRepoId,
@@ -145,8 +143,7 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 		},
 		{
 			{
-				Plugin:     "refdiff",
-				SkipOnFail: false,
+				Plugin: "refdiff",
 				Options: map[string]interface{}{
 					"tagsLimit":   10,
 					"tagsOrder":   "reverse semver",
@@ -198,7 +195,7 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 		validator.New(),
 	)
 
-	plans, scopes, err := MakePipelinePlanV200(testSubTaskMeta, testConnectionID, bpScopes)
+	plans, scopes, err := MakePipelinePlanV200(testSubTaskMeta, testConnectionID, bpScopes, syncPolicy)
 	assert.Equal(t, err, nil)
 
 	assert.Equal(t, expectPlans, plans)
diff --git a/plugins/gitlab/api/blueprint_v200.go b/plugins/gitlab/api/blueprint_v200.go
index 81e929903..7019cd4d2 100644
--- a/plugins/gitlab/api/blueprint_v200.go
+++ b/plugins/gitlab/api/blueprint_v200.go
@@ -21,6 +21,7 @@ import (
 	"fmt"
 	"net/url"
 	"strconv"
+	"time"
 
 	"github.com/apache/incubator-devlake/errors"
 	"github.com/apache/incubator-devlake/utils"
@@ -35,7 +36,7 @@ import (
 	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
-func MakePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64, scope []*core.BlueprintScopeV200) (core.PipelinePlan, []core.Scope, errors.Error) {
+func MakePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64, scope []*core.BlueprintScopeV200, syncPolicy *core.BlueprintSyncPolicy) (core.PipelinePlan, []core.Scope, errors.Error) {
 	var err errors.Error
 	connection := new(models.GitlabConnection)
 	err1 := connectionHelper.FirstById(connection, connectionId)
@@ -48,7 +49,7 @@ func MakePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64,
 		return nil, nil, err
 	}
 
-	pp, err := makePipelinePlanV200(subtaskMetas, scope, connection)
+	pp, err := makePipelinePlanV200(subtaskMetas, scope, connection, syncPolicy)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -101,7 +102,7 @@ func makeScopeV200(connectionId uint64, scopes []*core.BlueprintScopeV200) ([]co
 	return sc, nil
 }
 
-func makePipelinePlanV200(subtaskMetas []core.SubTaskMeta, scopes []*core.BlueprintScopeV200, connection *models.GitlabConnection) (core.PipelinePlan, errors.Error) {
+func makePipelinePlanV200(subtaskMetas []core.SubTaskMeta, scopes []*core.BlueprintScopeV200, connection *models.GitlabConnection, syncPolicy *core.BlueprintSyncPolicy) (core.PipelinePlan, errors.Error) {
 	plans := make(core.PipelinePlan, 0, 3*len(scopes))
 	for _, scope := range scopes {
 		var stage core.PipelineStage
@@ -128,7 +129,9 @@ func makePipelinePlanV200(subtaskMetas []core.SubTaskMeta, scopes []*core.Bluepr
 		options := make(map[string]interface{})
 		options["connectionId"] = connection.ID
 		options["projectId"] = intScopeId
-		options["entities"] = scope.Entities
+		if syncPolicy.CreatedDateAfter != nil {
+			options["createdDateAfter"] = syncPolicy.CreatedDateAfter.Format(time.RFC3339)
+		}
 
 		// construct subtasks
 		subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, scope.Entities)
diff --git a/plugins/gitlab/impl/impl.go b/plugins/gitlab/impl/impl.go
index b779b498f..fac31b7e4 100644
--- a/plugins/gitlab/impl/impl.go
+++ b/plugins/gitlab/impl/impl.go
@@ -65,8 +65,8 @@ func (plugin Gitlab) TransformationRule() interface{} {
 	return &models.GitlabTransformationRule{}
 }
 
-func (plugin Gitlab) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*core.BlueprintScopeV200) (core.PipelinePlan, []core.Scope, errors.Error) {
-	return api.MakePipelinePlanV200(plugin.SubTaskMetas(), connectionId, scopes)
+func (plugin Gitlab) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*core.BlueprintScopeV200, syncPolicy core.BlueprintSyncPolicy) (core.PipelinePlan, []core.Scope, errors.Error) {
+	return api.MakePipelinePlanV200(plugin.SubTaskMetas(), connectionId, scopes, &syncPolicy)
 }
 
 func (plugin Gitlab) GetTablesInfo() []core.Tabler {
@@ -156,7 +156,7 @@ func (plugin Gitlab) PrepareTaskData(taskCtx core.TaskContext, options map[strin
 
 	var createdDateAfter time.Time
 	if op.CreatedDateAfter != "" {
-		createdDateAfter, err = errors.Convert01(time.Parse("2006-01-02T15:04:05Z", op.CreatedDateAfter))
+		createdDateAfter, err = errors.Convert01(time.Parse(time.RFC3339, op.CreatedDateAfter))
 		if err != nil {
 			return nil, errors.BadInput.Wrap(err, "invalid value for `createdDateAfter`")
 		}
diff --git a/plugins/gitlab/tasks/issue_collector.go b/plugins/gitlab/tasks/issue_collector.go
index 1ea0c7203..5592dfe72 100644
--- a/plugins/gitlab/tasks/issue_collector.go
+++ b/plugins/gitlab/tasks/issue_collector.go
@@ -25,6 +25,7 @@ import (
 	"github.com/apache/incubator-devlake/plugins/helper"
 	"net/http"
 	"net/url"
+	"time"
 )
 
 const RAW_ISSUE_TABLE = "gitlab_api_issues"
@@ -57,10 +58,10 @@ func CollectApiIssues(taskCtx core.SubTaskContext) errors.Error {
 		Query: func(reqData *helper.RequestData) (url.Values, errors.Error) {
 			query := url.Values{}
 			if incremental {
-				query.Set("updated_after", collectorWithState.LatestState.LatestSuccessStart.String())
+				query.Set("updated_after", collectorWithState.LatestState.LatestSuccessStart.Format(time.RFC3339))
 			}
 			if collectorWithState.CreatedDateAfter != nil {
-				query.Set("created_after", collectorWithState.CreatedDateAfter.String())
+				query.Set("created_after", collectorWithState.CreatedDateAfter.Format(time.RFC3339))
 			}
 			query.Set("sort", "asc")
 			query.Set("page", fmt.Sprintf("%v", reqData.Pager.Page))
diff --git a/plugins/gitlab/tasks/mr_collector.go b/plugins/gitlab/tasks/mr_collector.go
index 6b2fb7316..e4dddcf8d 100644
--- a/plugins/gitlab/tasks/mr_collector.go
+++ b/plugins/gitlab/tasks/mr_collector.go
@@ -22,6 +22,7 @@ import (
 	"github.com/apache/incubator-devlake/plugins/core"
 	"github.com/apache/incubator-devlake/plugins/helper"
 	"net/url"
+	"time"
 )
 
 const RAW_MERGE_REQUEST_TABLE = "gitlab_api_merge_requests"
@@ -55,10 +56,10 @@ func CollectApiMergeRequests(taskCtx core.SubTaskContext) errors.Error {
 				return nil, err
 			}
 			if incremental {
-				query.Set("updated_after", collectorWithState.LatestState.LatestSuccessStart.String())
+				query.Set("updated_after", collectorWithState.LatestState.LatestSuccessStart.Format(time.RFC3339))
 			}
 			if collectorWithState.CreatedDateAfter != nil {
-				query.Set("created_after", collectorWithState.CreatedDateAfter.String())
+				query.Set("created_after", collectorWithState.CreatedDateAfter.Format(time.RFC3339))
 			}
 			return query, nil
 		},
diff --git a/plugins/jenkins/api/blueprint_v200.go b/plugins/jenkins/api/blueprint_v200.go
index 35c56e101..3e2f98875 100644
--- a/plugins/jenkins/api/blueprint_v200.go
+++ b/plugins/jenkins/api/blueprint_v200.go
@@ -19,6 +19,7 @@ package api
 
 import (
 	"fmt"
+	"time"
 
 	"github.com/apache/incubator-devlake/errors"
 	"github.com/apache/incubator-devlake/models/domainlayer"
@@ -31,9 +32,9 @@ import (
 	"github.com/apache/incubator-devlake/utils"
 )
 
-func MakeDataSourcePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64, bpScopes []*core.BlueprintScopeV200) (core.PipelinePlan, []core.Scope, errors.Error) {
+func MakeDataSourcePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64, bpScopes []*core.BlueprintScopeV200, syncPolicy *core.BlueprintSyncPolicy) (core.PipelinePlan, []core.Scope, errors.Error) {
 	plan := make(core.PipelinePlan, len(bpScopes))
-	plan, err := makeDataSourcePipelinePlanV200(subtaskMetas, plan, bpScopes, connectionId)
+	plan, err := makeDataSourcePipelinePlanV200(subtaskMetas, plan, bpScopes, connectionId, syncPolicy)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -50,6 +51,7 @@ func makeDataSourcePipelinePlanV200(
 	plan core.PipelinePlan,
 	bpScopes []*core.BlueprintScopeV200,
 	connectionId uint64,
+	syncPolicy *core.BlueprintSyncPolicy,
 ) (core.PipelinePlan, errors.Error) {
 	for i, bpScope := range bpScopes {
 		stage := plan[i]
@@ -60,6 +62,9 @@ func makeDataSourcePipelinePlanV200(
 		options := make(map[string]interface{})
 		options["scopeId"] = bpScope.Id
 		options["connectionId"] = connectionId
+		if syncPolicy.CreatedDateAfter != nil {
+			options["createdDateAfter"] = syncPolicy.CreatedDateAfter.Format(time.RFC3339)
+		}
 		subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, bpScope.Entities)
 		if err != nil {
 			return nil, err
diff --git a/plugins/jenkins/api/blueprint_v200_test.go b/plugins/jenkins/api/blueprint_v200_test.go
index 09b22b507..9083c2423 100644
--- a/plugins/jenkins/api/blueprint_v200_test.go
+++ b/plugins/jenkins/api/blueprint_v200_test.go
@@ -38,12 +38,13 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 		Id:       "a/b/ccc",
 		Name:     "",
 	}
+	syncPolicy := &core.BlueprintSyncPolicy{}
 	bpScopes := make([]*core.BlueprintScopeV200, 0)
 	bpScopes = append(bpScopes, bs)
 
 	basicRes = NewMockBasicRes()
 	plan := make(core.PipelinePlan, len(bpScopes))
-	plan, err = makeDataSourcePipelinePlanV200(nil, plan, bpScopes, 1)
+	plan, err = makeDataSourcePipelinePlanV200(nil, plan, bpScopes, 1, syncPolicy)
 	assert.Nil(t, err)
 	basicRes = NewMockBasicRes()
 	scopes, err := makeScopesV200(bpScopes, 1)
@@ -52,9 +53,8 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 	expectPlan := core.PipelinePlan{
 		core.PipelineStage{
 			{
-				Plugin:     "jenkins",
-				Subtasks:   []string{},
-				SkipOnFail: false,
+				Plugin:   "jenkins",
+				Subtasks: []string{},
 				Options: map[string]interface{}{
 					"connectionId": uint64(1),
 					"scopeId":      "a/b/ccc",
diff --git a/plugins/jenkins/impl/impl.go b/plugins/jenkins/impl/impl.go
index 35ba87bb6..49a28b884 100644
--- a/plugins/jenkins/impl/impl.go
+++ b/plugins/jenkins/impl/impl.go
@@ -154,7 +154,7 @@ func (plugin Jenkins) PrepareTaskData(taskCtx core.TaskContext, options map[stri
 
 	var createdDateAfter time.Time
 	if op.CreatedDateAfter != "" {
-		createdDateAfter, err = errors.Convert01(time.Parse("2006-01-02T15:04:05Z", op.CreatedDateAfter))
+		createdDateAfter, err = errors.Convert01(time.Parse(time.RFC3339, op.CreatedDateAfter))
 		if err != nil {
 			return nil, errors.BadInput.Wrap(err, "invalid value for `createdDateAfter`")
 		}
@@ -183,8 +183,8 @@ func (plugin Jenkins) MakePipelinePlan(connectionId uint64, scope []*core.Bluepr
 	return api.MakePipelinePlanV100(plugin.SubTaskMetas(), connectionId, scope)
 }
 
-func (plugin Jenkins) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*core.BlueprintScopeV200) (pp core.PipelinePlan, sc []core.Scope, err errors.Error) {
-	return api.MakeDataSourcePipelinePlanV200(plugin.SubTaskMetas(), connectionId, scopes)
+func (plugin Jenkins) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*core.BlueprintScopeV200, syncPolicy core.BlueprintSyncPolicy) (pp core.PipelinePlan, sc []core.Scope, err errors.Error) {
+	return api.MakeDataSourcePipelinePlanV200(plugin.SubTaskMetas(), connectionId, scopes, &syncPolicy)
 }
 
 func (plugin Jenkins) ApiResources() map[string]map[string]core.ApiResourceHandler {
diff --git a/plugins/jira/api/blueprint_v200.go b/plugins/jira/api/blueprint_v200.go
index fb5e26067..cafcefa9b 100644
--- a/plugins/jira/api/blueprint_v200.go
+++ b/plugins/jira/api/blueprint_v200.go
@@ -28,11 +28,12 @@ import (
 	"github.com/apache/incubator-devlake/plugins/helper"
 	"github.com/apache/incubator-devlake/plugins/jira/models"
 	"github.com/apache/incubator-devlake/utils"
+	"time"
 )
 
-func MakeDataSourcePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64, bpScopes []*core.BlueprintScopeV200) (core.PipelinePlan, []core.Scope, errors.Error) {
+func MakeDataSourcePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64, bpScopes []*core.BlueprintScopeV200, syncPolicy *core.BlueprintSyncPolicy) (core.PipelinePlan, []core.Scope, errors.Error) {
 	plan := make(core.PipelinePlan, len(bpScopes))
-	plan, err := makeDataSourcePipelinePlanV200(subtaskMetas, plan, bpScopes, connectionId)
+	plan, err := makeDataSourcePipelinePlanV200(subtaskMetas, plan, bpScopes, connectionId, syncPolicy)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -49,6 +50,7 @@ func makeDataSourcePipelinePlanV200(
 	plan core.PipelinePlan,
 	bpScopes []*core.BlueprintScopeV200,
 	connectionId uint64,
+	syncPolicy *core.BlueprintSyncPolicy,
 ) (core.PipelinePlan, errors.Error) {
 	for i, bpScope := range bpScopes {
 		stage := plan[i]
@@ -59,6 +61,9 @@ func makeDataSourcePipelinePlanV200(
 		options := make(map[string]interface{})
 		options["scopeId"] = bpScope.Id
 		options["connectionId"] = connectionId
+		if syncPolicy.CreatedDateAfter != nil {
+			options["createdDateAfter"] = syncPolicy.CreatedDateAfter.Format(time.RFC3339)
+		}
 
 		subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, bpScope.Entities)
 		if err != nil {
diff --git a/plugins/jira/api/blueprint_v200_test.go b/plugins/jira/api/blueprint_v200_test.go
index 5f9a9e209..ad49ec3bb 100644
--- a/plugins/jira/api/blueprint_v200_test.go
+++ b/plugins/jira/api/blueprint_v200_test.go
@@ -37,10 +37,11 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 		Entities: []string{"TICKET"},
 		Id:       "10",
 	}
+	syncPolicy := &core.BlueprintSyncPolicy{}
 	bpScopes := make([]*core.BlueprintScopeV200, 0)
 	bpScopes = append(bpScopes, bs)
 	plan := make(core.PipelinePlan, len(bpScopes))
-	plan, err = makeDataSourcePipelinePlanV200(nil, plan, bpScopes, uint64(1))
+	plan, err = makeDataSourcePipelinePlanV200(nil, plan, bpScopes, uint64(1), syncPolicy)
 	assert.Nil(t, err)
 	basicRes = NewMockBasicRes()
 	scopes, err := makeScopesV200(bpScopes, uint64(1))
@@ -49,9 +50,8 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
 	expectPlan := core.PipelinePlan{
 		core.PipelineStage{
 			{
-				Plugin:     "jira",
-				Subtasks:   []string{},
-				SkipOnFail: false,
+				Plugin:   "jira",
+				Subtasks: []string{},
 				Options: map[string]interface{}{
 					"connectionId": uint64(1),
 					"scopeId":      "10",
diff --git a/plugins/jira/impl/impl.go b/plugins/jira/impl/impl.go
index 7c5d8e262..67fe3f87e 100644
--- a/plugins/jira/impl/impl.go
+++ b/plugins/jira/impl/impl.go
@@ -195,7 +195,7 @@ func (plugin Jira) PrepareTaskData(taskCtx core.TaskContext, options map[string]
 
 	var createdDateAfter time.Time
 	if op.CreatedDateAfter != "" {
-		createdDateAfter, err = errors.Convert01(time.Parse("2006-01-02T15:04:05Z", op.CreatedDateAfter))
+		createdDateAfter, err = errors.Convert01(time.Parse(time.RFC3339, op.CreatedDateAfter))
 		if err != nil {
 			return nil, errors.BadInput.Wrap(err, "invalid value for `createdDateAfter`")
 		}
@@ -226,8 +226,8 @@ func (plugin Jira) MakePipelinePlan(connectionId uint64, scope []*core.Blueprint
 	return api.MakePipelinePlanV100(plugin.SubTaskMetas(), connectionId, scope)
 }
 
-func (plugin Jira) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*core.BlueprintScopeV200) (pp core.PipelinePlan, sc []core.Scope, err errors.Error) {
-	return api.MakeDataSourcePipelinePlanV200(plugin.SubTaskMetas(), connectionId, scopes)
+func (plugin Jira) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*core.BlueprintScopeV200, syncPolicy core.BlueprintSyncPolicy) (pp core.PipelinePlan, sc []core.Scope, err errors.Error) {
+	return api.MakeDataSourcePipelinePlanV200(plugin.SubTaskMetas(), connectionId, scopes, &syncPolicy)
 }
 
 func (plugin Jira) RootPkgPath() string {
diff --git a/plugins/tapd/impl/impl.go b/plugins/tapd/impl/impl.go
index 86f8f1461..c72855203 100644
--- a/plugins/tapd/impl/impl.go
+++ b/plugins/tapd/impl/impl.go
@@ -184,7 +184,7 @@ func (plugin Tapd) PrepareTaskData(taskCtx core.TaskContext, options map[string]
 
 	var since time.Time
 	if op.Since != "" {
-		since, err = errors.Convert01(time.Parse("2006-01-02T15:04:05Z", op.Since))
+		since, err = errors.Convert01(time.Parse(time.RFC3339, op.Since))
 		if err != nil {
 			return nil, errors.BadInput.Wrap(err, "invalid value for `since`")
 		}
diff --git a/plugins/webhook/impl/impl.go b/plugins/webhook/impl/impl.go
index 5689d676f..b3dfdcfc6 100644
--- a/plugins/webhook/impl/impl.go
+++ b/plugins/webhook/impl/impl.go
@@ -48,7 +48,7 @@ func (plugin Webhook) GetTablesInfo() []core.Tabler {
 	return []core.Tabler{}
 }
 
-func (plugin Webhook) MakeDataSourcePipelinePlanV200(connectionId uint64, _ []*core.BlueprintScopeV200) (pp core.PipelinePlan, sc []core.Scope, err errors.Error) {
+func (plugin Webhook) MakeDataSourcePipelinePlanV200(connectionId uint64, _ []*core.BlueprintScopeV200, _ core.BlueprintSyncPolicy) (pp core.PipelinePlan, sc []core.Scope, err errors.Error) {
 	return api.MakeDataSourcePipelinePlanV200(connectionId)
 }
 
diff --git a/runner/run_task.go b/runner/run_task.go
index 56fa381bf..5a59d4f9f 100644
--- a/runner/run_task.go
+++ b/runner/run_task.go
@@ -51,6 +51,10 @@ func RunTask(
 	if task.Status == models.TASK_COMPLETED {
 		return errors.Default.New("invalid task status")
 	}
+	dbPipeline := &models.DbPipeline{}
+	if err := db.Find(dbPipeline, task.PipelineId).Error; err != nil {
+		return errors.Convert(err)
+	}
 	log, err := getTaskLogger(parentLogger, task)
 	if err != nil {
 		return errors.Convert(err)
@@ -66,7 +70,7 @@ func RunTask(
 			default:
 				e = fmt.Errorf("%v", et)
 			}
-			if !task.SkipOnFail {
+			if !dbPipeline.SkipOnFail {
 				err = errors.Default.Wrap(e, fmt.Sprintf("run task failed with panic (%s)", utils.GatherCallFrames(0)))
 			}
 		}
@@ -137,7 +141,7 @@ func RunTask(
 		options,
 		progress,
 	)
-	if err != nil && task.SkipOnFail {
+	if dbPipeline.SkipOnFail {
 		return nil
 	}
 	return err
diff --git a/services/blueprint.go b/services/blueprint.go
index d85ddfa75..81fa3b0cd 100644
--- a/services/blueprint.go
+++ b/services/blueprint.go
@@ -24,7 +24,6 @@ import (
 	"strings"
 
 	"github.com/apache/incubator-devlake/errors"
-
 	"github.com/apache/incubator-devlake/logger"
 	"github.com/apache/incubator-devlake/models"
 	"github.com/apache/incubator-devlake/plugins/core"
@@ -315,6 +314,7 @@ func createPipelineByBlueprint(blueprint *models.Blueprint) (*models.Pipeline, e
 	newPipeline.Name = blueprint.Name
 	newPipeline.BlueprintId = blueprint.ID
 	newPipeline.Labels = blueprint.Labels
+	newPipeline.SkipOnFail = blueprint.SkipOnFail
 	pipeline, err := CreatePipeline(&newPipeline)
 	// Return all created tasks to the User
 	if err != nil {
@@ -328,13 +328,17 @@ func createPipelineByBlueprint(blueprint *models.Blueprint) (*models.Pipeline, e
 func MakePlanForBlueprint(blueprint *models.Blueprint) (core.PipelinePlan, errors.Error) {
 	bpSettings := new(models.BlueprintSettings)
 	err := errors.Convert(json.Unmarshal(blueprint.Settings, bpSettings))
-
 	if err != nil {
 		return nil, errors.Default.Wrap(err, fmt.Sprintf("settings:%s", string(blueprint.Settings)))
 	}
+
+	bpSyncPolicy := core.BlueprintSyncPolicy{}
+	bpSyncPolicy.CreatedDateAfter = bpSettings.CreatedDateAfter
+
 	var plan core.PipelinePlan
 	switch bpSettings.Version {
 	case "1.0.0":
+		// Notice: v1 not complete SkipOnFail & CreatedDateAfter
 		plan, err = GeneratePlanJsonV100(bpSettings)
 	case "2.0.0":
 		if blueprint.ProjectName == "" {
@@ -347,7 +351,7 @@ func MakePlanForBlueprint(blueprint *models.Blueprint) (core.PipelinePlan, error
 		for _, projectMetric := range projectMetrics {
 			metrics[projectMetric.PluginName] = json.RawMessage(projectMetric.PluginOption)
 		}
-		plan, err = GeneratePlanJsonV200(blueprint.ProjectName, bpSettings, metrics)
+		plan, err = GeneratePlanJsonV200(blueprint.ProjectName, bpSyncPolicy, bpSettings, metrics)
 	default:
 		return nil, errors.Default.New(fmt.Sprintf("unknown version of blueprint settings: %s", bpSettings.Version))
 	}
diff --git a/services/blueprint_makeplan_v100.go b/services/blueprint_makeplan_v100.go
index c8bb2227f..c32c7f873 100644
--- a/services/blueprint_makeplan_v100.go
+++ b/services/blueprint_makeplan_v100.go
@@ -54,7 +54,6 @@ func GeneratePlanJsonV100(settings *models.BlueprintSettings) (core.PipelinePlan
 		}
 		for _, stage := range plans[i] {
 			for _, task := range stage {
-				task.SkipOnFail = settings.SkipOnFail
 				if task.Plugin == "dora" {
 					hasDoraEnrich = true
 					for k, v := range task.Options {
diff --git a/services/blueprint_makeplan_v200.go b/services/blueprint_makeplan_v200.go
index ac78cb58f..997cec2d2 100644
--- a/services/blueprint_makeplan_v200.go
+++ b/services/blueprint_makeplan_v200.go
@@ -30,11 +30,12 @@ import (
 // GeneratePlanJsonV200 generates pipeline plan according v2.0.0 definition
 func GeneratePlanJsonV200(
 	projectName string,
+	syncPolicy core.BlueprintSyncPolicy,
 	sources *models.BlueprintSettings,
 	metrics map[string]json.RawMessage,
 ) (core.PipelinePlan, errors.Error) {
 	// generate plan and collect scopes
-	plan, scopes, err := genPlanJsonV200(projectName, sources, metrics)
+	plan, scopes, err := genPlanJsonV200(projectName, syncPolicy, sources, metrics)
 	if err != nil {
 		return nil, err
 	}
@@ -57,6 +58,7 @@ func GeneratePlanJsonV200(
 
 func genPlanJsonV200(
 	projectName string,
+	syncPolicy core.BlueprintSyncPolicy,
 	sources *models.BlueprintSettings,
 	metrics map[string]json.RawMessage,
 ) (core.PipelinePlan, []core.Scope, errors.Error) {
@@ -72,7 +74,7 @@ func genPlanJsonV200(
 	sourcePlans := make([]core.PipelinePlan, len(connections))
 	scopes := make([]core.Scope, 0, len(connections))
 	for i, connection := range connections {
-		if len(connection.Scopes) == 0 {
+		if len(connection.Scopes) == 0 && connection.Plugin != `webhook` {
 			return nil, nil, errors.Default.New(fmt.Sprintf("connections[%d].scope is empty", i))
 		}
 		plugin, err := core.GetPlugin(connection.Plugin)
@@ -84,6 +86,7 @@ func genPlanJsonV200(
 			sourcePlans[i], pluginScopes, err = pluginBp.MakeDataSourcePipelinePlanV200(
 				connection.ConnectionId,
 				connection.Scopes,
+				syncPolicy,
 			)
 			if err != nil {
 				return nil, nil, err
diff --git a/services/blueprint_makeplan_v200_test.go b/services/blueprint_makeplan_v200_test.go
index 21a646066..50ed56722 100644
--- a/services/blueprint_makeplan_v200_test.go
+++ b/services/blueprint_makeplan_v200_test.go
@@ -35,6 +35,7 @@ func TestMakePlanV200(t *testing.T) {
 	githubName := "TestMakePlanV200-github" // mimic github
 	// mock github plugin as a data source plugin
 	githubConnId := uint64(1)
+	syncPolicy := core.BlueprintSyncPolicy{}
 	githubScopes := []*core.BlueprintScopeV200{
 		{Id: "", Name: "apache/incubator-devlake"},
 		{Id: "", Name: "apache/incubator-devlake-website"},
@@ -54,7 +55,7 @@ func TestMakePlanV200(t *testing.T) {
 		&ticket.Board{DomainEntity: domainlayer.DomainEntity{Id: "github:GithubRepo:1:123"}, Name: "apache/incubator-devlake"},
 	}
 	github := new(mocks.CompositeDataSourcePluginBlueprintV200)
-	github.On("MakeDataSourcePipelinePlanV200", githubConnId, githubScopes).Return(githubOutputPlan, githubOutputScopes, nil)
+	github.On("MakeDataSourcePipelinePlanV200", githubConnId, githubScopes, syncPolicy).Return(githubOutputPlan, githubOutputScopes, nil)
 
 	// mock dora plugin as a metric plugin
 	doraName := "TestMakePlanV200-dora"
@@ -89,7 +90,7 @@ func TestMakePlanV200(t *testing.T) {
 		doraName: nil,
 	}
 
-	plan, scopes, err := genPlanJsonV200(projectName, sources, metrics)
+	plan, scopes, err := genPlanJsonV200(projectName, syncPolicy, sources, metrics)
 	assert.Nil(t, err)
 
 	assert.Equal(t, expectedPlan, plan)
diff --git a/services/pipeline_helper.go b/services/pipeline_helper.go
index b0706ce1b..d9300e76b 100644
--- a/services/pipeline_helper.go
+++ b/services/pipeline_helper.go
@@ -58,6 +58,7 @@ func CreateDbPipeline(newPipeline *models.NewPipeline) (*models.DbPipeline, erro
 		Message:       "",
 		SpentSeconds:  0,
 		Plan:          string(planByte),
+		SkipOnFail:    newPipeline.SkipOnFail,
 	}
 	if newPipeline.BlueprintId != 0 {
 		dbPipeline.BlueprintId = newPipeline.BlueprintId
@@ -210,6 +211,7 @@ func parsePipeline(dbPipeline *models.DbPipeline) *models.Pipeline {
 		Message:       dbPipeline.Message,
 		SpentSeconds:  dbPipeline.SpentSeconds,
 		Stage:         dbPipeline.Stage,
+		SkipOnFail:    dbPipeline.SkipOnFail,
 		Labels:        labelList,
 	}
 	return &pipeline
@@ -231,6 +233,7 @@ func parseDbPipeline(pipeline *models.Pipeline) *models.DbPipeline {
 		Message:       pipeline.Message,
 		SpentSeconds:  pipeline.SpentSeconds,
 		Stage:         pipeline.Stage,
+		SkipOnFail:    pipeline.SkipOnFail,
 	}
 	dbPipeline.Labels = []models.DbPipelineLabel{}
 	for _, label := range pipeline.Labels {
diff --git a/services/task.go b/services/task.go
index 022450488..f81db2cba 100644
--- a/services/task.go
+++ b/services/task.go
@@ -153,7 +153,6 @@ func CreateTask(newTask *models.NewTask) (*models.Task, errors.Error) {
 		PipelineId:  newTask.PipelineId,
 		PipelineRow: newTask.PipelineRow,
 		PipelineCol: newTask.PipelineCol,
-		SkipOnFail:  newTask.SkipOnFail,
 	}
 	err = db.Save(&task).Error
 	if err != nil {
@@ -238,7 +237,6 @@ func SpawnTasks(input []models.Task) ([]models.Task, errors.Error) {
 		task.BeganAt = nil
 		task.FinishedAt = nil
 		task.SpentSeconds = 0
-		task.SkipOnFail = true
 		result = append(result, task)
 	}
 	err := db.Save(&result).Error