From 94b2af7faa3893ba831ec3e6f56ca5e7bc03a131 Mon Sep 17 00:00:00 2001 From: Jonathan Tamsut Date: Mon, 22 May 2023 16:28:18 -0700 Subject: [PATCH 1/2] add architecture docs --- docs/images/lsp-illustration.png | Bin 0 -> 27047 bytes docs/images/system-components.png | Bin 0 -> 42077 bytes docs/project-architecture.md | 47 ++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 docs/images/lsp-illustration.png create mode 100644 docs/images/system-components.png create mode 100644 docs/project-architecture.md diff --git a/docs/images/lsp-illustration.png b/docs/images/lsp-illustration.png new file mode 100644 index 0000000000000000000000000000000000000000..66aabf5711d3659685b7008d5550ea79fb8a5a16 GIT binary patch literal 27047 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 BtKa|t literal 0 HcmV?d00001 diff --git a/docs/images/system-components.png b/docs/images/system-components.png new file mode 100644 index 0000000000000000000000000000000000000000..fc88f55d5313cc7d1397964fb3159cda8170a7ec GIT binary patch literal 42077 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∓=hCp z-}4t)EYR%C6|!G8s4n!w2YW6s8jF}R7#DF0N6`LyM-f+|+u78kp@1aiA)NdwtM0WJ zw5eq5*J5>n*?{<2h+%{_$B!4fPM&mi@~Rlt-tSeU@2#>A4xbKFApd^mPmJVj+MrsS z%5SXhYF0A0W{c?Y!h%N*`as;j9Q3O@-|-cGiGJVJV{5l+jI{n&Fdr>4D54T|{J zcMaED9?LvCtS)?m_y&sf_QH5@7ZIF!o+sf4lB;A-;!y25m*z&TW7(Cg{V#0XnfP`8 zmWJapJ;l!+d6isODqO{jt|_W8t9Gp3k#X3(%zK0T$4hk6|JN~N@*?LHamJ;?F_TkR z7*$c>rJ8jwQiFTxL-3tTr!#az_CASR7aR||^P@FBYbiO-Ufz(CNJ(U7`*RC~l3aqFP(I)=s2YlsBBPtUFc_e`3BDmri zf@w0s|7rPRAhV5OxFF-}k3W%|cuI7w>pAN$!?0DbPB3+v!NUKalYTydYT7+oBVnD* zA!=d^`d3&uu=3j*w}t=uD2HvzTdUMdOfl_v-uq@+nbMg;B8Q#JqgEe|0ORi@BY7j$ zmm`5(31PYh4lmb#)b{I|0gRu8NpI`0vvgzX%mT~m`}NL}hUIt$J_;1`U^@dcU3WTm zG=@&{r;VTA^?lzqa@lw8niLc;Py9t@?VoEF>MI#WRs@kBZel31?_Wwk{2=O}cjy|Lv z80j^O6EaoYwgGbBnR0fE{A>J2r6+_1JZt76q&=w1Ie?-x=7tH2GI1*dLw73I_G;Gd zhi9%zKf25N;?DV)i=Nx8#k|oUVQ*XCRb_8~!@cT+bPDa%Mbj^Ow9N|Gg2peSXTxJ2t<>}@9VSeZF^#sSe(tcBc}$|IYUeTs-t1CuV@^4v4kOq7cw*)ze_ z!$Vy%F~%gh0~dDS-O-&XyG!0=@$!f!A#4}Zeo6BaVqC!S`q;J%N zdV?$;u5ku>)6N?zMR_)z=4d2!pK?;{9Jv={Q;9>~f<5ac34BGVku0tS)nK&>vO#e? zKef}%cvmzRP_rfH6j7=>(d?QNC?<>BP`T6JZVBmNZ}F(@BVBwJLH_wc-2ow!2(GI( z8=a}4ByAI$04t@+MOkn$x0A!wvRyQQfzA1mcv(3q@4cVH9UP%HNhpGgnEVVwSKay* z`o^gZh)Uv`M7xkqLh?D<3$Hg3%5iw)Z!k>xxhzv_+~X7 z`Nau8;mu^6r8bll-TqC3MQMTdJxa7fQIXB^U|Q&gQvS&MMOt7YWD^q+?#`egouBS^ z@h1e-eIqZoYhugqQQR_;*FV}ceg@><{jEi=!A#gz?Pnf4-t&qg)b>p^Q(KYreeJ95 zl{BqOUP;IcG$+`vZzQeILQz?!lK#RO_}2m0Z(c6qhi}(IeBA#P^~sYrE7o*r0$-7r zFEkz$!#wwAU+Ko!9?h1Ux=OWTdn+{5m&(!0-na7#Y`95sHR}kLJr?N(!waptB};%B zZ4SB^P;U(+rz+>L+tUtl;<*b~q1+zOI^(x^>-1~2qgdgOd6)dPMt#KU00~KDcMU!R z#1n~^lLqE(vA*o(A6#7kN!$vus|rBZ(YX=rr=qiQbekaw#|AWdy`JwLK2P!4u4B(Q zbTKc>)1E;ovU7-a;1t`l<%o`hMVP>-1F>z)GEw+piS?V>b%d)fZR8K$@t>!&A@W%I zCaR{mcOmTd^wE+-Nm;(~?)o^NgK<4|%gwYmB=4UV&}-+trw@f5-sa-@3F6}yiygOK zD@jle9!%skzU<~cT;~GcP)1Yoe)rCQZ~Upg?UMF9t1#w#YXu9jt;O_XtHTMicVdKA z6dCFtVogLGbE+s1PK=z_g-Ws>l@U)%IPsO?RrX9x8W?`D3%5UtwGkHlQ#4G;OrJPi zIXi#6Y?R%)^TS*^O?;;-)>*J4EWNe#py#lF3zd`a&QHY2DqDd?a^i;29Z-o-T(WCw(gN*Bv=u9_GmgvaHXMroLwXn&jM4dxiR0{wl%Qvf(UEikQh`& zG$!(~sEw6xL0DpNsVU;0_k0z8>|*bG3}Y|JPqXu@8Q>%ZJeWsas=BBCbWjF3_&?^% z^y9X38Zf|*dGBL$s2cREIryr;_T^v+w{VL&(D1AZ?Uw|m)rGimN3J_J_SDw~$MI@H1-{R**IbRZoYKJ_8-L?4ZFMr^%uWIhwhp;G{?k>@0fFBCvu@e@LVjaca~Rw$T?!4x zUP_)Tn>I{fxe;S^kOlc(-^4hvyY_QK(y8q$X+L&8r=rW0aX($ zcl?AqfJ}~>I_=uptNuRKKOBPJ98}xYhtCa*99#Y*?5&iRt@Iu)j{&&~3LN#1ty&rq zsW+0;VcF0rFJJOxAtk{%t(g3z^6!26|H8aXDV& z^4?qT8FYWRqkw6b+v&wPj}vIsfQ;PyFMOqzEz;|qv0MWt<{Vd7atV;y{VH*B@#b;g zRVqpKAg3j6@`1rY>vdz4u>Um85Zn&wv%q5NVSt*(E$;??&_}7&tZvFaZjZl$+N(dE zXJRBczB6X*j5pnbw9Dc@)W2agI@n!cndVsDgC@DnFs-c)A6(G3Txt_;JJ^A(kgWBY zuS)2(c+Ltn=L_^T8l69VvllEbApRo%T0 z`#{l1ZP5z08f*6|!%zu47}PX1!M$OXdn!_tn37WCdnZ}+R`2y$h?r$_VxlDA-S{Kr zHaEmjU^Vy^y;mfMPTbGk(-j7@=Z2xO5xGZN^`S|1Up@s-58%eEXurpC9K=&_cEINd zc+j+C&4z`T?Glke(F7}tZqHedJwn{l?$!Od<>hy?rr!XmB7$C_r>an;>)m>&k#Ap& zb6-r{Y(Lm%Qga78uoCUu&4HilJB5>bbD;Yu4V$qG6(mV3E zv=rtp$-XIs!zDJ{&-?)Hj#ePf&clVtW#z8Nk-a`eKM1#r8^t}_nI#Foa**U1DCfIx zU~HUBjaV8hRj%>C(b_XrgI$-fZfiUogd&X;Ildy}oRihn8>aqym^!i64F+{z$zd`_ zd`4A=l;hZi2)W((s+v`5S?A@CRE({W4Fgj#d>aoNav8x}mE&&7WgIe>SWLW)4QW~5 zzNY6s!_VHFcxCdbr`@{cP^Dw4M$*+QMJc~->~l3aH^~2M2$ktcYWVkqE&S#iZ<*wl zL2eClCfy#h{ux2gqU7f0rYLw`H?jW|m?ud@XP#w#T}9kX!l{2)gTQA#pN8g@b>cjL zSSBDX+J^n^Ce|F(2WP@J1Co6E4N9z5Om-qn_YF<-{iYst){%1GNcBK0q7I^;Og6Ug z!P+BV%%)m}Vv@U-o{tJ*s{7^!}ee8(Y613dlY=i_L}!kb3}(rJE+j* zhoz%6hl|avme=QC9YWh9B5Xr$80wXG62kds*}k|F+|*r$%Rj>u@zQaZhXJ}29Y2p3F#XVK!rnyCKwjuYvvvDo(^A3V;!@BsA1{1L_hSFaL zglosu+)4JiJV_3L%inOX!}xhp_U?0nHdqefk3?pov4#1M^I~*f2jL`z~c`p`w_Ejw` za}0rGH#?G>G*Xg~;lF}hy%m7ZVyJlBTJf-Dl&%G?PByjq6DDb!4;N#f9RZJKh*dkB z2ocv`a~UXLvPLE~&MRis$y=Up$!<6HG=~TUOYwZL;c2g4V0_uUacVr$z;$x}>{dtO zjI{NxT&ZmBj^H|?i+&1X6?b;jelsC%N_M=mP2o6rr!_|MJHoZ)>$B-i>h}VA)x0_| zjbg_WZ2I3KLxfAvA)xAAF4S(W0BOOD*f0GiA=rg`8=b(Nw)&$lfh{da-qH5}uMsf+ zl*PwzYs4QLyfOatQ{}Yb`n|xwsDlZAU-KDn$C{R!owf9Fg$v*%UtxC@E*;4(Nhc6t z(d7AC4b~m6nxzQG80nR(#v4plhwEh06_4=IvDz@5h%C%4Mib86eywU>oz!)AAgDik zkG@$zyt=|KsH4WUyWz!yM5J#ga%Y!SB6;LWWJ^t)#9;dce>HeZubTxBTWH2^uaB-=Z{OEmku`fXp z!gZU|Kl5sm(s%6#t8UzLORp8$yYcRJ8uy7Fwq#MsDHdbE)AW5a0eoAecSX39!&LZ} zSjgWgITeOJ=h7J#L4V#q@bcGz6heB64qdctc_Q4)JH~6VXzYT&p%FU~5XE3u-g@@a z;UK?h0C+@qm)YijOAtHqNa&=27k;;Jn*U$u?$5P_&H_02Kjq9o07?FD8B%|n_X}Z4 z`IMQ#P934!n{6w|NZ5H`>0fm8m!OpWVqgg5g#L#O$e5;=Nn`kMLHeKd_?Mr0Q+{j- zygQ%`M}K}n;^pn#&@p8HU~vREep+`7#lFFse9VgyI9ieAG zdg%rL;5QUuvj0@+Mrj(T6mY*Y<>D{%^Dl3c{IfO?Y&a~@&=|$;3UiBnU z8tMP6Th4!E_d1L%eoHdI+yF=Z?}1|em*AJK;b8%XPRr6qvnlLDPck&#`t3L9R03#$6M5EuK{5NtC z$PYxc9-K&4p$8URKta4*DF77feXvLyXnWS$HXErqiOuO}hZ_GiX_Qir5lM8C9BmtV zh-VnOS|&kiaSwrt%ld(_-1OQDwO~Ur@()iQ{oPo7d~^Wuqto?G=R=;>xY$FOEnvMK zNO?R&)}${^X9ONg7Gn#}%2BWgvJKmG+fP@$7!bgd7HC!dU?btlKm@YF%sI2b)I(%z zjw3M|UzdoZi+qGK*psQYX!%k?vf)%VL> zx~d#fbee@xk45=fZr+oj@nAd&wP8AfHjkj4!1+@uWeBVAy*QoCvXI!LH)YMLduL`) zNS$PJtm8zt7e2_wGHkR`z&kqlkr>G%!HH*&EiYS{(shvZIoHGYT?eCh`3|HZDBVUx-)H?6gD%E7C;pX;Wc#7O_-Tpv+H`! z{r92)2NJ;ZA9y9W9}eFeXTAp!Cm@Ia=UB(#lTcDvizpqps@UL(TUj%5>hQIEtt3dXJrJzU2^DlgnG z^AHxT1Az1ZrSu612u5a^iGB6G6!VI5d)BX*|0SP}J!tJ0e?l0@Zr}C2NqyKhZ>Y*A zl#1&hAk)=1_W%_L-a0q!Yd$o8^C3b@06+6C>8ulQ3#FtJYN4z zY{ft0sDCxYPt5LLFZSCpI^IO3Zy<#MN2~*_j8*@JHrX9388GTFR5d;1|07gYUh`L| z>fgxJZ}Ik{l;5NAe~2dklMq>OpW}A+3G|8o=2g742BS9^jN5<={hwga&*%Q}Yco9n zUa*t>m5cL_YjpS%uOKi+%4qHWY1m(`(M%7NYH6w``{Q-h4nyfnpA7$aa1F3-(@(ww zGNZp-?k}XO2LPhg@I?%NJSYdOlAf$Se|iz6v@)O@dlY`eG=KjF=N(}5{rA`Wen1qt XvKk~SNPFoR@K5!Y*3E+JX3zdFNuA4` literal 0 HcmV?d00001 diff --git a/docs/project-architecture.md b/docs/project-architecture.md new file mode 100644 index 00000000..be42b370 --- /dev/null +++ b/docs/project-architecture.md @@ -0,0 +1,47 @@ +# Project Architecture + +This is a high-level overview of the Visual Studio Code Extension. The intended audience is someone interested in contributing the extension. + +## Background + +Visual Studio Code provides an [API](https://code.visualstudio.com/api/language-extensions/overview) for implementing language-specific editing features in an extension. In VS Code, a language editor extension has two main components: + +- a **language client** which is a normal VS Code extension that listens to different editor events and sends the payloads of these events to a language server +- a **language server** which is performs language analysis on the code written within VSCode (this runs in a separate process for performance reasons) + +The language client and server communicate via the Language Server Protocol. The [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) defines a standardized communication protocol between an editor (in our case Visual Studio Code) and a language server that implements features like autocomplete and syntax checking. + +![LSP Illustration](./images/lsp-illustration.png) + +By making the extension LSP compliant we have set the extension up to integrate with other text editors in the future. + +Fundamentally, the extension takes in a string of text (YAML specifying a GitHub Actions workflow) and needs to make sense of the text. Conceptually, what this extension does is similar to what other compilers and interpreters (e.g., [LLVM](https://aosabook.org/en/v1/llvm.html)) do. The basic steps form a pipeline, with the output of one step serving as the input to the next step. Broadly speaking the steps involved are: + +1. A lexer takes in a stream of text (in this case a workflow file) and breaks the text into the atomic chunks of the language called tokens +2. Next, the tokens are fed into the parser which constructs a tree representation of the program +3. Lastly, the tree is evaluated. This step takes the syntax tree as input and produces a literal value. + +_Crafting Interpreters_ - which can be read freely online [here](https://craftinginterpreters.com/contents.html) - goes into much greater depth about compiler/interpreter development. + +## Architecture + +The [VS Code extension](https://github.com/github/vscode-github-actions) integrates with Visual Studio code and uses [open-source libraries](https://github.com/actions/languageservices/tree/main) in order to provide its full functionality. The extension initializes the language server and performs other non-language related tasks like adding functionality to the VS Code sidebar. + +The open-source language libraries that the extension uses are: + +- The [language server](https://github.com/actions/languageservices/tree/main/languageserver) library is a wrapper around the language service + - it handles the connection with VS Code via the Language Service Protocol + - makes API calls to GitHub (e.g., requesting [Action secrets](https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28)) for repository and workflow information +- The [language service](https://github.com/actions/languageservices/tree/main/languageservice) library uses the workflow parser and expression engine (described below) to implement the core functionality of the extension + - it calls into the language server for any data that requires an API call +- the [workflow-parser](https://github.com/actions/languageservices/tree/main/workflow-parser) library parses GitHub Actions workflows into an intermediate representation and validates that the workflow file is syntactically valid + - the workflow parser uses a [JSON schema](https://github.com/actions/languageservices/blob/main/workflow-parser/src/workflow-v1.0.json) to parse the workflow file + - the schema defines the list of valid tokens and their arguments +- the [expressions](https://github.com/actions/languageservices/tree/main/expressions) engine is used to parse and evaluate GitHub Actions [expressions](https://docs.github.com/en/actions/learn-github-actions/expressions) + +![system-components](./images/system-components.png) + +## Useful Links + +- [actions/languageservices](https://github.com/actions/languageservices) is the monorepo where all language services code for GitHub Actions can be found +- [GitHub Actions Expression Language Documentation](https://docs.github.com/en/actions/learn-github-actions/expressions) \ No newline at end of file From d4093cddcdec618b1b9ab7d24ade0afa7c2bd386 Mon Sep 17 00:00:00 2001 From: Jonathan Tamsut Date: Mon, 22 May 2023 16:31:07 -0700 Subject: [PATCH 2/2] add link to architecture docs in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4dc87bf0..8d418444 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Unfortunately, at this time we are not able to support the extension with [remot ## Contributing -See [CONTRIBUTING.md](CONTRIBUTING.md). +See [CONTRIBUTING.md](CONTRIBUTING.md). A description of the architecture of the extension can be found [here](./docs/project-architecture.md). ## License