{"id":403590,"date":"2024-06-29T17:12:52","date_gmt":"2024-06-29T17:12:52","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=403590"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-06-29T17:12:52","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=403590","title":{"rendered":"<span>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 HCL-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447 \u0432 Jira. #2<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><a href=\"https:\/\/habr.com\/ru\/post\/697500\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 1<\/a><\/p>\n<p>\u0421\u0440\u0430\u0437\u0443 \u043e\u0433\u043e\u0432\u043e\u0440\u044e\u0441\u044c, \u0447\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u0435\u0439 &#8212; \u043f\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043f\u0438\u043b\u043a\u0443 \u0437\u043d\u0430\u043d\u0438\u0439 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 HCL. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u043e \u0434\u0430\u0441\u0442 \u0441\u0442\u0438\u043c\u0443\u043b \u0434\u043b\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0432 HCL.<\/p>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u044f \u043d\u0435 \u043f\u0440\u0435\u0441\u043b\u0435\u0434\u0443\u044e \u0446\u0435\u043b\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c \u0447\u0438\u0441\u0442\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430 Go. <\/p>\n<p>\u0418 \u0432 \u0442\u0440\u0435\u0442\u044c\u0438\u0445, \u0434\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0433\u043b\u0443\u0431\u043e\u043a\u0438\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u0438 \u0437\u043d\u0430\u043d\u0438\u044f \u044f \u0442\u043e \u0436\u0435 \u043d\u0435 \u043c\u043e\u0433\u0443, \u0442\u0430\u043a \u043a\u0430\u043a \u0434\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u0432\u0435\u0449\u0435\u0439 \u0434\u043e\u0445\u043e\u0436\u0443 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u043f\u0440\u043e\u0431 \u0438 \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c.<\/p>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0431\u044b\u043b \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d HCL. \u041d\u0430\u0447\u043d\u0435\u043c \u0435\u0433\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0438 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0430\u0442\u044c \u043a \u043c\u043e\u0438\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 Issue<\/p>\n<pre><code class=\"ruby\">create \"Task\" {   project          = \"AG\"             # required   # required   summary          = \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"   # optional   description      = &lt;&lt;DESC \u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress DESC   app_layer        = \"Backend\"        # optional   components       = [\"service_A\"]    # optional   sprint           = 100              # optional   epic             = \"AG-6815\"        # optional   labels           = [\"need-regress\"] # optional   story_point      = 2                # optional   qa_story_point   = 1                # optional   assignee         = \"user_A\"         # optional   developer        = \"user_A\"         # optional   team_lead        = \"user_B\"         # optional   tech_lead        = \"user_B\"         # optional   release_engineer = \"user_C\"         # optional   tester           = \"user_D\"         # optional   #  parent           = \"AA-1234\"     # optional, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f Sub-Task }  # \u0438 \u0442\u0430\u043a \u0435\u0449\u0435 \u0448\u0442\u0443\u043a 20, \u043c\u0435\u043d\u044f\u044f service_A \u043d\u0430 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u043e\u0434 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0438\u0445 \u0432 <em>jira.Issue<\/em>, \u0442\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e 20+ \u043f\u043e\u0445\u043e\u0436\u0438\u0445 \u0437\u0430\u0434\u0430\u0447. \u041d\u043e \u044d\u0442\u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0438\u043c\u0435\u0435\u0442 \u043a\u0443\u0447\u0443 \u043d\u0435\u0443\u0434\u043e\u0431\u0441\u0442\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u043c \u0443\u043b\u0443\u0447\u0448\u0430\u0442\u044c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0442 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u0447\u0442\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u044b \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f:<\/p>\n<pre><code>Error: Unsupported argument    on example.hcl line 10, in create \"Task\":   10:   app_layer        = \"Backend\"        # optional  An argument named \"app_layer\" is not expected here.  Error: Unsupported argument    on example.hcl line 11, in create \"Task\":   11:   components       = [\"service_A\"]    # optional  An argument named \"components\" is not expected here.  Error: Unsupported argument    on example.hcl line 20, in create \"Task\":   20:   team_lead        = \"user_B\"         # optional  An argument named \"team_lead\" is not expected here. ...<\/code><\/pre>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0442\u0443\u0434\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u0435\u0439:<\/p>\n<pre><code class=\"go\">type config struct { Type            string   `hcl:\"type,label\"` Project         string   `hcl:\"project\"` Summary         string   `hcl:\"summary\"` Description     string   `hcl:\"description,optional\"` AppLayer        string   `hcl:\"app_layer,optional\"` Components      []string `hcl:\"components,optional\"` SprintId        int      `hcl:\"sprint,optional\"` Epic            string   `hcl:\"epic,optional\"` Labels          []string `hcl:\"labels,optional\"` StoryPoint      int      `hcl:\"story_point,optional\"` QaStoryPoint    int      `hcl:\"qa_story_point,optional\"` Assignee        string   `hcl:\"assignee,optional\"` Developer       string   `hcl:\"developer,optional\"` TeamLead        string   `hcl:\"team_lead,optional\"` TechLead        string   `hcl:\"tech_lead,optional\"` ReleaseEngineer string   `hcl:\"release_engineer,optional\"` Tester          string   `hcl:\"tester,optional\"` Parent          string   `hcl:\"parent,optional\"` }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c:<\/p>\n<pre><code>&amp;main.Root{     Create: {         {             Type:            \"Task\",             Project:         \"AG\",             Summary:         \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\",             Description:     \"\u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.\\n\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress\\n\",             AppLayer:        \"Backend\",             Components:      {\"service_A\"},             SprintId:        100,             Epic:            \"AG-6815\",             Labels:          {\"need-regress\"},             StoryPoint:      2,             QaStoryPoint:    1,             Assignee:        \"user_A\",             Developer:       \"user_A\",             TeamLead:        \"user_B\",             TechLead:        \"user_B\",             ReleaseEngineer: \"user_C\",             Tester:          \"user_D\",             Parent:          \"\",         },     }, } <\/code><\/pre>\n<p>\u041f\u0430\u0440\u0441\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 ?<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0437\u0430\u0434\u0430\u0447\u043a\u0435 \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438. \u0427\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043d\u0435 \u0432\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c, \u043a\u0430\u043a \u0432 Jira \u0437\u0430\u0432\u0435\u0434\u0435\u043d\u044b \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0438, \u0438 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043e\u043f\u0435\u0447\u0430\u0442\u043e\u043a, \u0445\u043e\u0447\u0443 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043b\u044f \u043d\u0438\u0445 &#171;\u0430\u043b\u0438\u0430\u0441\u044b&#187;, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0449\u0435 \u0437\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c.<\/p>\n<h2>\u0421\u043f\u043e\u0441\u043e\u0431 1<\/h2>\n<p>\u0421\u0430\u043c\u043e\u0435 \u043f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0443\u043c, \u044d\u0442\u043e \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432 \u043a\u043e\u0434\u0435, \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <em>DecodeBody<\/em> \u0435\u0441\u0442\u044c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <em>context<\/em>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0434\u043e\u043a\u0438:<\/p>\n<pre><code class=\"go\">ctx := &amp;hcl.EvalContext{ Variables: map[string]cty.Value{ \"name\": cty.StringVal(\"Ermintrude\"), \"age\":  cty.NumberIntVal(32), \"path\": cty.ObjectVal(map[string]cty.Value{ \"root\":    cty.StringVal(rootDir), \"module\":  cty.StringVal(moduleDir), \"current\": cty.StringVal(currentDir), }), }, Functions: map[string]function.Function{ \"upper\":  stdlib.UpperFunc, \"lower\":  stdlib.LowerFunc, \"min\":    stdlib.MinFunc, \"max\":    stdlib.MaxFunc, \"strlen\": stdlib.StrlenFunc, \"substr\": stdlib.SubstrFunc, }, }<\/code><\/pre>\n<pre><code class=\"ruby\">message = \"${name} is ${age} ${age == 1 ? \"year\" : \"years\"} old!\" source_file = \"${path.module}\/foo.txt\" message = \"HELLO, ${upper(name)}!\"<\/code><\/pre>\n<p>\u0417\u0430\u0431\u0435\u0433\u0430\u044f \u0432\u043f\u0435\u0440\u0435\u0434, \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0438\u043f\u043e\u0432 <a href=\"https:\/\/github.com\/zclconf\/go-cty\" rel=\"noopener noreferrer nofollow\"><u>zclconf\/go-cty<\/u><\/a><\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u043d\u0430\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"go\">... ctx := &amp;hcl.EvalContext{ Variables: map[string]cty.Value{ \"tester\":           cty.StringVal(\"jira_user_1\"), \"team_lead\":        cty.StringVal(\"jira_user_5\"), \"tech_lead\":        cty.StringVal(\"jira_user_5\"), \"release_engineer\": cty.StringVal(\"jira_user_6\"), \"developers\": cty.ObjectVal(map[string]cty.Value{ \"Alex\":  cty.StringVal(\"jira_user_2\"), \"Igor\":  cty.StringVal(\"jira_user_3\"), \"Denis\": cty.StringVal(\"jira_user_4\"), }), \"services\": cty.ObjectVal(map[string]cty.Value{ \"service_A\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_A\"), }), \"service_B\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_B\"), }), \"service_C\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_C\"), }), }), }, }  var root Root diags = gohcl.DecodeBody(f.Body, ctx, &amp;root) ...<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"ruby\">create \"Task\" {   project          = \"AG\"             # required   # required   summary          = \"${services.service_A.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"   # optional   description      = &lt;&lt;DESC \u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress DESC   app_layer        = \"Backend\"          # optional   components       = [\"${services.service_A.name}\"]      # optional   sprint           = 100                # optional   epic             = \"AG-6815\"          # optional   labels           = [\"need-regress\"]   # optional   story_point      = 2                  # optional   qa_story_point   = 1                  # optional   assignee         = developers.Alex    # optional   developer        = developers.Alex    # optional   team_lead        = team_lead          # optional   tech_lead        = tech_lead          # optional   release_engineer = release_engineer   # optional   tester           = tester }<\/code><\/pre>\n<p>\u0421 \u043f\u043e\u043b\u043d\u044b\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 HCL \u043c\u043e\u0436\u043d\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f <a href=\"https:\/\/github.com\/hashicorp\/hcl2\/blob\/master\/hcl\/hclsyntax\/spec.md\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u0434:<\/p>\n<pre><code>&amp;main.Root{     Create: {         {             Type:            \"Task\",             Project:         \"AG\",             Summary:         \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\",             Description:     \"\u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.\\n\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress\\n\",             AppLayer:        \"Backend\",             Components:      {\"service_A\"},             SprintId:        100,             Epic:            \"AG-6815\",             Labels:          {\"need-regress\"},             StoryPoint:      2,             QaStoryPoint:    1,             Assignee:        \"jira_user_2\",             Developer:       \"jira_user_2\",             TeamLead:        \"jira_user_5\",             TechLead:        \"jira_user_5\",             ReleaseEngineer: \"jira_user_6\",             Tester:          \"jira_user_1\",             Parent:          \"\",         },     }, } <\/code><\/pre>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e. <\/p>\n<h2>\u0421\u043f\u043e\u0441\u043e\u0431 2<\/h2>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435, \u0447\u0442\u043e \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e \u043d\u0430 \u0443\u043c \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043b\u0438\u0431\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <em>env<\/em> \u043b\u0438\u0431\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <em>env<\/em>() \u0432 <em>EvalContext<\/em>.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b, \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <em>env<\/em>. \u0421\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0434\u043e\u043a\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <em>upper<\/em>, \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438.<\/p>\n<pre><code class=\"go\">var EnvFunc = function.New(&amp;function.Spec{ Params: []function.Parameter{ { Name:             \"env\", Type:             cty.String, AllowDynamicType: true, }, }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { in := args[0].AsString() out := os.Getenv(in) return cty.StringVal(out), nil }, })  ...  ctx := &amp;hcl.EvalContext{ Variables: map[string]cty.Value{ \"team_lead\":        cty.StringVal(\"jira_user_5\"), \"tech_lead\":        cty.StringVal(\"jira_user_5\"), \"release_engineer\": cty.StringVal(\"jira_user_6\"), \"services\": cty.ObjectVal(map[string]cty.Value{ \"service_A\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_A\"), }), \"service_B\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_B\"), }), \"service_C\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_C\"), }), }), }, Functions: map[string]function.Function{ \"env\": EnvFunc, }, }<\/code><\/pre>\n<p>\u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438:<\/p>\n<pre><code class=\"bash\">export DEVELOPER_ALEX=\"jira_user_2\" export DEVELOPER_IGOR=\"jira_user_3\" export DEVELOPER_DENIS=\"jira_user_4\" export JIRA_TESTER=\"jira_user_1\"<\/code><\/pre>\n<p>\u0414\u043e\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c hcl-\u0448\u0430\u0431\u043b\u043e\u043d<\/p>\n<pre><code class=\"ruby\">create \"Task\" {   project          = \"AG\"             # required   # required   summary          = \"${services.service_A.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"   # optional   description      = &lt;&lt;DESC \u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress DESC   app_layer        = \"Backend\"          # optional   components       = [\"${services.service_A.name}\"]      # optional   sprint           = 100                # optional   epic             = \"AG-6815\"          # optional   labels           = [\"need-regress\"]   # optional   story_point      = 2                  # optional   qa_story_point   = 1                  # optional   assignee         = env(\"DEVELOPER_ALEX\")    # optional   developer        = env(\"DEVELOPER_ALEX\")    # optional   team_lead        = team_lead          # optional   tech_lead        = tech_lead          # optional   release_engineer = release_engineer   # optional   tester           = env(\"JIRA_TESTER\") # optional }<\/code><\/pre>\n<p>\u0418 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c:<\/p>\n<pre><code>&amp;main.Root{     Create: {         {             Type:            \"Task\",             Project:         \"AG\",             Summary:         \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\",             Description:     \"\u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.\\n\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress\\n\",             AppLayer:        \"Backend\",             Components:      {\"service_A\"},             SprintId:        100,             Epic:            \"AG-6815\",             Labels:          {\"need-regress\"},             StoryPoint:      2,             QaStoryPoint:    1,             Assignee:        \"jira_user_2\",             Developer:       \"jira_user_2\",             TeamLead:        \"jira_user_5\",             TechLead:        \"jira_user_5\",             ReleaseEngineer: \"jira_user_6\",             Tester:          \"jira_user_1\",             Parent:          \"\",         },     }, } <\/code><\/pre>\n<p>\u0421 \u044d\u0442\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u0443\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u0438. \u041d\u043e, \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043d\u0435 \u0442\u043e, \u0447\u0435\u0433\u043e \u044f \u043e\u0436\u0438\u0434\u0430\u044e.<\/p>\n<h2>\u0421\u043f\u043e\u0441\u043e\u0431 3<\/h2>\n<p>\u0410 \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 \u0441\u0430\u043c\u043e\u043c HCL, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043f\u043e\u0442\u043e\u043c \u0441\u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:<\/p>\n<pre><code class=\"ruby\">variables {   developers       = [\"jira_user_2\", \"jira_user_3\", \"jira_user_4\"]   tester           = \"jira_user_1\"   team_lead        = \"jira_user_5\"   tech_lead        = \"jira_user_5\"   release_engineer = \"jira_user_6\"   services         = [     { name = \"service_A\"},     { name = \"service_B\"},     { name = \"service_C\"},   ] }  # \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435  create \"Task\" {   project          = \"AG\"             # required   # required   summary          = \"${services.0.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"   # optional   description      = &lt;&lt;DESC \u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress DESC   app_layer        = \"Backend\"          # optional   components       = [\"${services.0.name}\"]      # optional   sprint           = 100                # optional   epic             = \"AG-6815\"          # optional   labels           = [\"need-regress\"]   # optional   story_point      = 2                  # optional   qa_story_point   = 1                  # optional   assignee         = developers.0       # optional   developer        = developers.0       # optional   team_lead        = team_lead          # optional   tech_lead        = tech_lead          # optional   release_engineer = release_engineer   # optional   tester           = tester             # optional }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0431\u0443\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c:<\/p>\n<pre><code>Error: Unsupported block type    on example.hcl line 1, in variables:    1: variables {  Blocks of type \"variables\" are not expected here.  Error: Invalid index    on example.hcl line 17, in create \"Task\":   17:   summary          = \"${services.0.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"  The given key does not identify an element in this collection value. An object only supports looking up attributes by name, not by numeric index.  ...<\/code><\/pre>\n<p>\u041e\u043a. \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0431\u043b\u043e\u043a <em>variables<\/em>. \u0414\u0430\u043b\u044c\u0448\u0435 \u0443 \u043d\u0430\u0441 \u0441\u043d\u043e\u0432\u0430 \u0440\u0430\u0437\u0432\u0438\u043b\u043a\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432: \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043b\u0438\u0431\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0445 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438. \u0412\u044b\u0431\u0438\u0440\u0430\u044e \u0432\u0442\u043e\u0440\u043e\u0435.<\/p>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u043c\u044b\u0441\u043b\u044c, \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"go\">type Root struct { Variables variables `hcl:\"variables,block\"` Create    []config  `hcl:\"create,block\"` }<\/code><\/pre>\n<p>\u041d\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043e\u0431\u044f\u0437\u0430\u043d\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0431\u043b\u043e\u043a\u0438 <em>variables<\/em> \u0438 <em>create.<\/em> \u0425\u043e\u0447\u0443 \u043f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u0431\u043b\u043e\u043a \u0431\u044b\u043b \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c, \u043d\u043e \u043f\u043e\u0439\u0434\u0435\u043c \u043f\u043e \u043f\u0443\u0442\u0438 \u043e\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043a \u0441\u043b\u043e\u0436\u043d\u043e\u043c\u0443.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u043b\u044f <em>variables<\/em>:<\/p>\n<pre><code class=\"go\">type variables struct { Variables hcl.Body `hcl:\",remain\"` }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c:<\/p>\n<pre><code>Error: Invalid index    on example.hcl line 17, in create \"Task\":   17:   summary          = \"${services.0.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"  The given key does not identify an element in this collection value. An object only supports looking up attributes by name, not by numeric index.  Error: Unsuitable value type    on example.hcl line 17, in create \"Task\":   17:   summary          = \"${services.0.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"  Unsuitable value: value must be known  ...<\/code><\/pre>\n<p>\u041e\u043a, \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u043b\u043e\u043a <em>variables<\/em>, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u0437 \u043d\u0435\u0433\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0441\u043d\u043e\u0432\u0430 \u043f\u0430\u0440\u0441\u0438\u0442\u044c, \u043d\u043e \u0443\u0436\u0435 \u0431\u043b\u043e\u043a\u0438 <em>create<\/em>.<\/p>\n<p>\u0417\u043d\u0430\u0447\u0438\u0442 \u0442\u0430\u043a\u0430\u044f Root-\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043d\u0430\u043c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0434\u0440\u0443\u0433\u0443\u044e (\u043f\u0440\u0438\u0448\u043b\u0430 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043f\u043e\u043a\u0430 \u043f\u0438\u0441\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u044e):<\/p>\n<pre><code class=\"go\">type VariablesBlock struct { Variables   variables `hcl:\"variables,block\"` Remains     hcl.Body  `hcl:\",remain\"` }  type variables struct { Remains hcl.Body `hcl:\",remain\"` }  type CreateBlocks struct { Create []createConfig `hcl:\"create,block\"` }  type createConfig struct { Type            string   `hcl:\"type,label\"` Project         string   `hcl:\"project\"` Summary         string   `hcl:\"summary\"` Description     string   `hcl:\"description,optional\"` AppLayer        string   `hcl:\"app_layer,optional\"` Components      []string `hcl:\"components,optional\"` SprintId        int      `hcl:\"sprint,optional\"` Epic            string   `hcl:\"epic,optional\"` Labels          []string `hcl:\"labels,optional\"` StoryPoint      int      `hcl:\"story_point,optional\"` QaStoryPoint    int      `hcl:\"qa_story_point,optional\"` Assignee        string   `hcl:\"assignee,optional\"` Developer       string   `hcl:\"developer,optional\"` TeamLead        string   `hcl:\"team_lead,optional\"` TechLead        string   `hcl:\"tech_lead,optional\"` ReleaseEngineer string   `hcl:\"release_engineer,optional\"` Tester          string   `hcl:\"tester,optional\"` Parent          string   `hcl:\"parent,optional\"` }<\/code><\/pre>\n<p>\u0418 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u044e: \u043f\u0430\u0440\u0441\u0438\u043d\u0433 <em>variables<\/em>, \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438, \u043f\u0430\u0440\u0441\u0438\u043d\u0433 <em>create.<\/em><\/p>\n<pre><code class=\"go\">parser := hclparse.NewParser() f, diags := parser.ParseHCLFile(filename) if diags.HasErrors() { renderDiags(diags, parser.Files())  return nil, diags }  var variablesBlock VariablesBlock diags = gohcl.DecodeBody(f.Body, nil, &amp;variablesBlock) if diags.HasErrors() { renderDiags(diags, parser.Files())  return nil, diags } ...<\/code><\/pre>\n<p>\u0421\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043e\u043a\u043d\u0435 \u0434\u0435\u0431\u0430\u0433\u0430, \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/090\/5b6\/a78\/0905b6a7873d032d10dc851f7a0abf6a.png\" width=\"914\" height=\"938\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/090\/5b6\/a78\/0905b6a7873d032d10dc851f7a0abf6a.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0440\u043e\u0434\u0435 \u0442\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e. \u041f\u0440\u043e\u0431\u0443\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435:<\/p>\n<pre><code class=\"go\">parser := hclparse.NewParser() ...      \/\/ \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b env \u0432 \u0431\u043b\u043e\u043a\u0435 variables ctx := &amp;hcl.EvalContext{ Variables: map[string]cty.Value{}, Functions: map[string]function.Function{ \"env\": EnvFunc, }, }      \/\/ \u043f\u0430\u0440\u0441\u0438\u043c \u0431\u043b\u043e\u043a variables var variablesBlock VariablesBlock diags = gohcl.DecodeBody(f.Body, ctx, &amp;variablesBlock) if diags.HasErrors() { renderDiags(diags, parser.Files())  return nil, diags }      \/\/ \u0442\u0430\u043a \u043a\u0430\u043a variablesBlock.Variables.Remains \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f hcl.Body     \/\/ \u0438 \u0432 \u0431\u043b\u043e\u043a\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0447\u0442\u043e\u0431\u044b \u0438\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u044c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434 hcl.Body.JustAttributes() variables, diags := variablesBlock.Variables.Remains.JustAttributes() if diags.HasErrors() { renderDiags(diags, parser.Files())  return nil, diags }      \/\/ \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u043f\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0445 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 for _, variable := range variables { var value cty.Value          \/\/ \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u043f\u0440\u043e\u0431 \u0438 \u043e\u0448\u0438\u0431\u043e\u043a, \u043f\u0440\u0438\u0448\u0435\u043b \u043a \u0442\u0430\u043a\u043e\u043c\u0443 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0443 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441 \u0442\u0438\u043f\u043e\u043c cty.Value diags := gohcl.DecodeExpression(variable.Expr, nil, &amp;value) if diags.HasErrors() { return nil, diags }  ctx.Variables[variable.Name] = value }  var createBlock CreateBlocks diags = gohcl.DecodeBody(variablesBlock.Remains, ctx, &amp;createBlock) if diags.HasErrors() { renderDiags(diags, parser.Files())  return nil, diags }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c<\/p>\n<pre><code>&amp;main.CreateBlocks{     Create: {         {             Type:            \"Task\",             Project:         \"AG\",             Summary:         \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\",             Description:     \"\u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.\\n\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress\\n\",             AppLayer:        \"Backend\",             Components:      {\"service_A\"},             SprintId:        100,             Epic:            \"AG-6815\",             Labels:          {\"need-regress\"},             StoryPoint:      2,             QaStoryPoint:    1,             Assignee:        \"jira_user_2\",             Developer:       \"jira_user_2\",             TeamLead:        \"jira_user_5\",             TechLead:        \"jira_user_5\",             ReleaseEngineer: \"jira_user_6\",             Tester:          \"jira_user_1\",             Parent:          \"\",         },     }, } <\/code><\/pre>\n<p>\u0415\u0441\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 ? \u0438 \u0432\u0440\u043e\u0434\u0435 \u0434\u0430 \u0436\u0435 \u0433\u043e\u0434\u043d\u044b\u0439.<\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0435\u043c \u0431\u043b\u043e\u043a <em>variables<\/em> \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 <em>variablesBlock.Variables.Remains<\/em><\/p>\n<pre><code class=\"go\">var variablesBlock VariablesBlock _ = gohcl.DecodeBody(f.Body, ctx, &amp;variablesBlock)  if variablesBlock.Variables.Remains != nil { variables, diags := variablesBlock.Variables.Remains.JustAttributes() if diags.HasErrors() { renderDiags(diags, parser.Files())  return nil, diags }  for key, variable := range variables { var value cty.Value  diags := gohcl.DecodeExpression(variable.Expr, nil, &amp;value) if diags.HasErrors() { return nil, diags }  ctx.Variables[key] = value } }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u043c \u0431\u043b\u043e\u043a\u043e\u043c <em>variables<\/em> \u0438 \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445<\/p>\n<pre><code class=\"ruby\">create \"Task\" {   project          = \"AG\"             # required   # required   summary          = \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"   # optional   description      = &lt;&lt;DESC \u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress DESC   app_layer        = \"Backend\"        # optional   components       = [\"service_A\"]    # optional   sprint           = 100              # optional   epic             = \"AG-6815\"        # optional   # optional   labels           = [\"need-regress\"]   story_point      = 2                # optional   qa_story_point   = 1                # optional   assignee         = \"user_A\"         # optional   developer        = \"user_A\"         # optional   team_lead        = \"user_B\"         # optional   tech_lead        = \"user_B\"         # optional   release_engineer = \"user_C\"         # optional   tester           = \"user_D\"         # optional   #  parent           = \"AA-1234\"     # optional, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f Sub-Task }<\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<pre><code>&amp;main.CreateBlocks{     Create: {         {             Type:            \"Task\",             Project:         \"AG\",             Summary:         \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\",             Description:     \"\u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.\\n\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress\\n\",             AppLayer:        \"Backend\",             Components:      {\"service_A\"},             SprintId:        100,             Epic:            \"AG-6815\",             Labels:          {\"need-regress\"},             StoryPoint:      2,             QaStoryPoint:    1,             Assignee:        \"user_A\",             Developer:       \"user_A\",             TeamLead:        \"user_B\",             TechLead:        \"user_B\",             ReleaseEngineer: \"user_C\",             Tester:          \"user_D\",             Parent:          \"\",         },     }, }<\/code><\/pre>\n<h2>\u0421\u043f\u043e\u0441\u043e\u0431 4<\/h2>\n<p>\u041a \u044d\u0442\u043e\u043c\u0443 \u0441\u043f\u043e\u0441\u043e\u0431\u0443 \u044f \u043f\u0440\u0438\u0448\u0435\u043b \u0434\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0438 \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 HCL, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u043f\u0440\u043e\u0431\u0443\u044e \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b.<\/p>\n<p>\u0418\u0434\u0435\u044f \u0442\u0430\u043a\u0430\u044f \u0436\u0435, \u043a\u0430\u043a \u0438 \u0432 \u0441\u043f\u043e\u0441\u043e\u0431\u0435 3, \u0441 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430\u043c\u0438, \u043d\u043e \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u0430 <em>hcl.Body.PartialContent<\/em>. <\/p>\n<p>\u041c\u0438\u043d\u0443\u0441, <em>PartialContent<\/em> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e \u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 <em>hcl.BodySchema<\/em>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f hcl-\u0444\u0430\u0439\u043b\u0430 \u0431\u043b\u043e\u043a\u0438 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442, \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435.<\/p>\n<pre><code class=\"go\">var variablesSchema = &amp;hcl.BodySchema{ Blocks: []hcl.BlockHeaderSchema{{Type: \"variables\"}}, }<\/code><\/pre>\n<p>\u0418 \u0441\u0430\u043c\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/p>\n<pre><code class=\"go\">blocks, body, diags := body.PartialContent(variablesSchema) if diags.HasErrors() {         renderDiags(diags, parser.Files())        return nil, diags }  for _, block := range blocks.Blocks { attrs, _ := block.Body.JustAttributes()  for key, attr := range attrs { var value cty.Value  diags := gohcl.DecodeExpression(attr.Expr, nil, &amp;hclVar.Value) if diags.HasErrors() {                 renderDiags(diags, parser.Files())                return nil, diags }  ctx.Variables[key] = value } }<\/code><\/pre>\n<p>\u0412\u043e\u043e\u0431\u0449\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 BodySchema \u043c\u043d\u0435 \u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u043e\u0441\u044c \u0438\u0437-\u0437\u0430 &#171;\u0441\u0432\u043e\u0435\u0439&#187; \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u043b\u043e\u043a\u0438 \u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b. \u041f\u0440\u0438\u0447\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043b\u043e\u043a\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f, \u0447\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438.<\/p>\n<pre><code class=\"go\">package hcl  \/\/ BlockHeaderSchema represents the shape of a block header, and is \/\/ used for matching blocks within bodies. type BlockHeaderSchema struct { Type       string LabelNames []string }  \/\/ AttributeSchema represents the requirements for an attribute, and is used \/\/ for matching attributes within bodies. type AttributeSchema struct { Name     string Required bool }  \/\/ BodySchema represents the desired shallow structure of a body. type BodySchema struct { Attributes []AttributeSchema Blocks     []BlockHeaderSchema }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0434\u0430\u0447, \u0447\u0435\u0440\u0435\u0437 \u0431\u043b\u043e\u043a\u0438 <em>create<\/em> \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0432 \u043c\u043e\u0438\u0445 \u0445\u043e\u0442\u0435\u043b\u043a\u0430\u0445 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u0441\u043f\u043e\u0441\u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0431\u043b\u043e\u043a\u0430 <em>create<\/em>. \u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0442\u0430\u043a\u0430\u044f: \u0443 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 (\u043b\u0438\u0431\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432), \u043d\u0443\u0436\u043d\u043e \u043f\u043e \u043d\u0435\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0446\u0438\u043a\u043b, \u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043e\u0434\u0438\u043d \u0448\u0430\u0431\u043b\u043e\u043d (\u0431\u043b\u043e\u043a create) \u0441\u043e\u0437\u0434\u0430\u0442\u044c N issue \u0432 Jira.<\/p>\n<p>\u041f\u0441\u0435\u0432\u0434\u043e-\u043a\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"ruby\">{% for service in services %}  create \"Task\" {     ...   summary          = \"${service.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"   components       = [\"${services.name}\"]   ... }  {% endfor %}<\/code><\/pre>\n<p>\u041f\u043e\u043a\u0430 \u0438\u0434\u0435\u0438 \u0434\u0432\u0435:<\/p>\n<p>\u0432 <em>create<\/em> \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442 for_each, \u043f\u0440\u0438 \u0430\u043d\u0430\u043b\u0438\u0437\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0446\u0438\u043a\u043b \u0438 \u043a\u0430\u043a-\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0446\u0438\u043a\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <em>iter<\/em><\/p>\n<pre><code>create \"Task\" {   ...   summary  = \"${iter.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"   ...   for_each = [for i, service in services: service if service.skip == false] }<\/code><\/pre>\n<p>\u043b\u0438\u0431\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c <em>create<\/em> \u0432\u043d\u0443\u0442\u0440\u044c \u043d\u043e\u0432\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <em>loop<\/em>, \u0438 \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u0445 <em>loop<\/em> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u0446\u0438\u043a\u043b\u0430<\/p>\n<pre><code>loop {   list = [for i, service in services: service if service.skip == false]    create \"Task\" {     ...     summary  = \"${iter.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"     ...   } }<\/code><\/pre>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/697590\/\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/697538\/\"> https:\/\/habr.com\/ru\/articles\/697538\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><a href=\"https:\/\/habr.com\/ru\/post\/697500\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 1<\/a><\/p>\n<p>\u0421\u0440\u0430\u0437\u0443 \u043e\u0433\u043e\u0432\u043e\u0440\u044e\u0441\u044c, \u0447\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u0435\u0439 &#8212; \u043f\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043f\u0438\u043b\u043a\u0443 \u0437\u043d\u0430\u043d\u0438\u0439 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 HCL. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u043e \u0434\u0430\u0441\u0442 \u0441\u0442\u0438\u043c\u0443\u043b \u0434\u043b\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0432 HCL.<\/p>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u044f \u043d\u0435 \u043f\u0440\u0435\u0441\u043b\u0435\u0434\u0443\u044e \u0446\u0435\u043b\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c \u0447\u0438\u0441\u0442\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430 Go. <\/p>\n<p>\u0418 \u0432 \u0442\u0440\u0435\u0442\u044c\u0438\u0445, \u0434\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0433\u043b\u0443\u0431\u043e\u043a\u0438\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u0438 \u0437\u043d\u0430\u043d\u0438\u044f \u044f \u0442\u043e \u0436\u0435 \u043d\u0435 \u043c\u043e\u0433\u0443, \u0442\u0430\u043a \u043a\u0430\u043a \u0434\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u0432\u0435\u0449\u0435\u0439 \u0434\u043e\u0445\u043e\u0436\u0443 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u043f\u0440\u043e\u0431 \u0438 \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c.<\/p>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0431\u044b\u043b \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d HCL. \u041d\u0430\u0447\u043d\u0435\u043c \u0435\u0433\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0438 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0430\u0442\u044c \u043a \u043c\u043e\u0438\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 Issue<\/p>\n<pre><code class=\"ruby\">create \"Task\" {   project          = \"AG\"             # required   # required   summary          = \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"   # optional   description      = &lt;&lt;DESC \u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress DESC   app_layer        = \"Backend\"        # optional   components       = [\"service_A\"]    # optional   sprint           = 100              # optional   epic             = \"AG-6815\"        # optional   labels           = [\"need-regress\"] # optional   story_point      = 2                # optional   qa_story_point   = 1                # optional   assignee         = \"user_A\"         # optional   developer        = \"user_A\"         # optional   team_lead        = \"user_B\"         # optional   tech_lead        = \"user_B\"         # optional   release_engineer = \"user_C\"         # optional   tester           = \"user_D\"         # optional   #  parent           = \"AA-1234\"     # optional, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f Sub-Task }  # \u0438 \u0442\u0430\u043a \u0435\u0449\u0435 \u0448\u0442\u0443\u043a 20, \u043c\u0435\u043d\u044f\u044f service_A \u043d\u0430 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u043e\u0434 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0438\u0445 \u0432 <em>jira.Issue<\/em>, \u0442\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e 20+ \u043f\u043e\u0445\u043e\u0436\u0438\u0445 \u0437\u0430\u0434\u0430\u0447. \u041d\u043e \u044d\u0442\u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0438\u043c\u0435\u0435\u0442 \u043a\u0443\u0447\u0443 \u043d\u0435\u0443\u0434\u043e\u0431\u0441\u0442\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u043c \u0443\u043b\u0443\u0447\u0448\u0430\u0442\u044c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0442 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u0447\u0442\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u044b \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f:<\/p>\n<pre><code>Error: Unsupported argument    on example.hcl line 10, in create \"Task\":   10:   app_layer        = \"Backend\"        # optional  An argument named \"app_layer\" is not expected here.  Error: Unsupported argument    on example.hcl line 11, in create \"Task\":   11:   components       = [\"service_A\"]    # optional  An argument named \"components\" is not expected here.  Error: Unsupported argument    on example.hcl line 20, in create \"Task\":   20:   team_lead        = \"user_B\"         # optional  An argument named \"team_lead\" is not expected here. ...<\/code><\/pre>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0442\u0443\u0434\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u0435\u0439:<\/p>\n<pre><code class=\"go\">type config struct { Type            string   `hcl:\"type,label\"` Project         string   `hcl:\"project\"` Summary         string   `hcl:\"summary\"` Description     string   `hcl:\"description,optional\"` AppLayer        string   `hcl:\"app_layer,optional\"` Components      []string `hcl:\"components,optional\"` SprintId        int      `hcl:\"sprint,optional\"` Epic            string   `hcl:\"epic,optional\"` Labels          []string `hcl:\"labels,optional\"` StoryPoint      int      `hcl:\"story_point,optional\"` QaStoryPoint    int      `hcl:\"qa_story_point,optional\"` Assignee        string   `hcl:\"assignee,optional\"` Developer       string   `hcl:\"developer,optional\"` TeamLead        string   `hcl:\"team_lead,optional\"` TechLead        string   `hcl:\"tech_lead,optional\"` ReleaseEngineer string   `hcl:\"release_engineer,optional\"` Tester          string   `hcl:\"tester,optional\"` Parent          string   `hcl:\"parent,optional\"` }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c:<\/p>\n<pre><code>&amp;main.Root{     Create: {         {             Type:            \"Task\",             Project:         \"AG\",             Summary:         \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\",             Description:     \"\u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.\\n\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress\\n\",             AppLayer:        \"Backend\",             Components:      {\"service_A\"},             SprintId:        100,             Epic:            \"AG-6815\",             Labels:          {\"need-regress\"},             StoryPoint:      2,             QaStoryPoint:    1,             Assignee:        \"user_A\",             Developer:       \"user_A\",             TeamLead:        \"user_B\",             TechLead:        \"user_B\",             ReleaseEngineer: \"user_C\",             Tester:          \"user_D\",             Parent:          \"\",         },     }, } <\/code><\/pre>\n<p>\u041f\u0430\u0440\u0441\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 ?<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0437\u0430\u0434\u0430\u0447\u043a\u0435 \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438. \u0427\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043d\u0435 \u0432\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c, \u043a\u0430\u043a \u0432 Jira \u0437\u0430\u0432\u0435\u0434\u0435\u043d\u044b \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0438, \u0438 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043e\u043f\u0435\u0447\u0430\u0442\u043e\u043a, \u0445\u043e\u0447\u0443 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043b\u044f \u043d\u0438\u0445 &#171;\u0430\u043b\u0438\u0430\u0441\u044b&#187;, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0449\u0435 \u0437\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c.<\/p>\n<h2>\u0421\u043f\u043e\u0441\u043e\u0431 1<\/h2>\n<p>\u0421\u0430\u043c\u043e\u0435 \u043f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0443\u043c, \u044d\u0442\u043e \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432 \u043a\u043e\u0434\u0435, \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <em>DecodeBody<\/em> \u0435\u0441\u0442\u044c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <em>context<\/em>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0434\u043e\u043a\u0438:<\/p>\n<pre><code class=\"go\">ctx := &amp;hcl.EvalContext{ Variables: map[string]cty.Value{ \"name\": cty.StringVal(\"Ermintrude\"), \"age\":  cty.NumberIntVal(32), \"path\": cty.ObjectVal(map[string]cty.Value{ \"root\":    cty.StringVal(rootDir), \"module\":  cty.StringVal(moduleDir), \"current\": cty.StringVal(currentDir), }), }, Functions: map[string]function.Function{ \"upper\":  stdlib.UpperFunc, \"lower\":  stdlib.LowerFunc, \"min\":    stdlib.MinFunc, \"max\":    stdlib.MaxFunc, \"strlen\": stdlib.StrlenFunc, \"substr\": stdlib.SubstrFunc, }, }<\/code><\/pre>\n<pre><code class=\"ruby\">message = \"${name} is ${age} ${age == 1 ? \"year\" : \"years\"} old!\" source_file = \"${path.module}\/foo.txt\" message = \"HELLO, ${upper(name)}!\"<\/code><\/pre>\n<p>\u0417\u0430\u0431\u0435\u0433\u0430\u044f \u0432\u043f\u0435\u0440\u0435\u0434, \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0438\u043f\u043e\u0432 <a href=\"https:\/\/github.com\/zclconf\/go-cty\" rel=\"noopener noreferrer nofollow\"><u>zclconf\/go-cty<\/u><\/a><\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u043d\u0430\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"go\">... ctx := &amp;hcl.EvalContext{ Variables: map[string]cty.Value{ \"tester\":           cty.StringVal(\"jira_user_1\"), \"team_lead\":        cty.StringVal(\"jira_user_5\"), \"tech_lead\":        cty.StringVal(\"jira_user_5\"), \"release_engineer\": cty.StringVal(\"jira_user_6\"), \"developers\": cty.ObjectVal(map[string]cty.Value{ \"Alex\":  cty.StringVal(\"jira_user_2\"), \"Igor\":  cty.StringVal(\"jira_user_3\"), \"Denis\": cty.StringVal(\"jira_user_4\"), }), \"services\": cty.ObjectVal(map[string]cty.Value{ \"service_A\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_A\"), }), \"service_B\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_B\"), }), \"service_C\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_C\"), }), }), }, }  var root Root diags = gohcl.DecodeBody(f.Body, ctx, &amp;root) ...<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"ruby\">create \"Task\" {   project          = \"AG\"             # required   # required   summary          = \"${services.service_A.name} \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\"   # optional   description      = &lt;&lt;DESC \u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress DESC   app_layer        = \"Backend\"          # optional   components       = [\"${services.service_A.name}\"]      # optional   sprint           = 100                # optional   epic             = \"AG-6815\"          # optional   labels           = [\"need-regress\"]   # optional   story_point      = 2                  # optional   qa_story_point   = 1                  # optional   assignee         = developers.Alex    # optional   developer        = developers.Alex    # optional   team_lead        = team_lead          # optional   tech_lead        = tech_lead          # optional   release_engineer = release_engineer   # optional   tester           = tester }<\/code><\/pre>\n<p>\u0421 \u043f\u043e\u043b\u043d\u044b\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 HCL \u043c\u043e\u0436\u043d\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f <a href=\"https:\/\/github.com\/hashicorp\/hcl2\/blob\/master\/hcl\/hclsyntax\/spec.md\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u0434:<\/p>\n<pre><code>&amp;main.Root{     Create: {         {             Type:            \"Task\",             Project:         \"AG\",             Summary:         \"service_A \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\",             Description:     \"\u041d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Library_A \u0434\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.\\n\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 regress\\n\",             AppLayer:        \"Backend\",             Components:      {\"service_A\"},             SprintId:        100,             Epic:            \"AG-6815\",             Labels:          {\"need-regress\"},             StoryPoint:      2,             QaStoryPoint:    1,             Assignee:        \"jira_user_2\",             Developer:       \"jira_user_2\",             TeamLead:        \"jira_user_5\",             TechLead:        \"jira_user_5\",             ReleaseEngineer: \"jira_user_6\",             Tester:          \"jira_user_1\",             Parent:          \"\",         },     }, } <\/code><\/pre>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e. <\/p>\n<h2>\u0421\u043f\u043e\u0441\u043e\u0431 2<\/h2>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435, \u0447\u0442\u043e \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e \u043d\u0430 \u0443\u043c \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043b\u0438\u0431\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <em>env<\/em> \u043b\u0438\u0431\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <em>env<\/em>() \u0432 <em>EvalContext<\/em>.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b, \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <em>env<\/em>. \u0421\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0434\u043e\u043a\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <em>upper<\/em>, \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438.<\/p>\n<pre><code class=\"go\">var EnvFunc = function.New(&amp;function.Spec{ Params: []function.Parameter{ { Name:             \"env\", Type:             cty.String, AllowDynamicType: true, }, }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { in := args[0].AsString() out := os.Getenv(in) return cty.StringVal(out), nil }, })  ...  ctx := &amp;hcl.EvalContext{ Variables: map[string]cty.Value{ \"team_lead\":        cty.StringVal(\"jira_user_5\"), \"tech_lead\":        cty.StringVal(\"jira_user_5\"), \"release_engineer\": cty.StringVal(\"jira_user_6\"), \"services\": cty.ObjectVal(map[string]cty.Value{ \"service_A\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_A\"), }), \"service_B\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_B\"), }), \"service_C\": cty.ObjectVal(map[string]cty.Value{ \"name\": cty.StringVal(\"service_C\"), }), }), }, Functions: map[string]function.Function{ \"env\": EnvFunc, }, }<\/code><\/pre>\n<p>\u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438:<\/p>\n<pre><code class=\"bash\">export DEVELOPER_ALEX=\"jira_user_2\" export<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-403590","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/403590","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=403590"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/403590\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=403590"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=403590"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=403590"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}