From d050620f0fa81c6e3d993d6ec3ac8490be88f8fc Mon Sep 17 00:00:00 2001 From: srinidhis Date: Thu, 7 Oct 2021 16:55:10 +0530 Subject: [PATCH] feat: gitpod demo --- .github/workflows/gitpod.yaml | 50 +++++++++++ example/gitpod/.gitignore | 25 ++++++ example/gitpod/Dockerfile | 17 ++++ example/gitpod/Jenkinsfile | 56 ++++++++++++ example/gitpod/LICENSE | 21 +++++ example/gitpod/Makefile | 90 +++++++++++++++++++ example/gitpod/README.md | 27 ++++++ example/gitpod/docs/simple-go-helloworld.png | Bin 0 -> 30416 bytes example/gitpod/go.mod | 3 + example/gitpod/go.sum | 0 example/gitpod/main.go | 71 +++++++++++++++ example/gitpod/main_test.go | 33 +++++++ example/gitpod/version | 1 + 13 files changed, 394 insertions(+) create mode 100644 .github/workflows/gitpod.yaml create mode 100644 example/gitpod/.gitignore create mode 100644 example/gitpod/Dockerfile create mode 100644 example/gitpod/Jenkinsfile create mode 100644 example/gitpod/LICENSE create mode 100644 example/gitpod/Makefile create mode 100644 example/gitpod/README.md create mode 100644 example/gitpod/docs/simple-go-helloworld.png create mode 100644 example/gitpod/go.mod create mode 100644 example/gitpod/go.sum create mode 100644 example/gitpod/main.go create mode 100644 example/gitpod/main_test.go create mode 100644 example/gitpod/version diff --git a/.github/workflows/gitpod.yaml b/.github/workflows/gitpod.yaml new file mode 100644 index 0000000..10faaad --- /dev/null +++ b/.github/workflows/gitpod.yaml @@ -0,0 +1,50 @@ +name: Gitpod +on: + push: + paths: + - 'example/gitpod/**' + +jobs: + gitpod: + runs-on: ubuntu-latest + name: Build Gitpod app + steps: + - name: checkout + id: checkout + uses: actions/checkout@v2 + with: + submodules: true + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + - name: docker login + uses: docker/login-action@v1 + with: + username: ${{ secrets.PUBLIC_DOCKER_USERNAME }} + password: ${{ secrets.PUBLIC_DOCKER_PASSWORD }} + # always uses a single image ,the changes are overridden + # to-do versioning of the builds in case required + - name: build configurator + uses: docker/build-push-action@v2 + with: + tags: razorpay/devstack:gitpod-${{ github.sha }} + push: true + file: ./example/gitpod/Dockerfile + + spinnaker: + runs-on: self-hosted + name: Spinnaker deploy + steps: + - name: deploy + run: | + echo 'Calling spinnaker deploy' + curl -X POST -H "Content-Type: application/json \ + -d '{ "commit_id" : gitpod-${{ github.sha }} }' \ + https://deploy-github-actions.razorpay.com/webhooks/webhook/gitpod-pid + exit 1 \ No newline at end of file diff --git a/example/gitpod/.gitignore b/example/gitpod/.gitignore new file mode 100644 index 0000000..e62c448 --- /dev/null +++ b/example/gitpod/.gitignore @@ -0,0 +1,25 @@ +*~ +*# +.#* +\#*# +.*.sw[a-z] +*.un~ +pkg/ + +# Berkshelf +.vagrant +/cookbooks +Berksfile.lock + +# Bundler +Gemfile.lock +bin/* +.bundle/* + +.kitchen/ +.kitchen.local.yml + +*.log + +# binaries +simple-go-helloworld diff --git a/example/gitpod/Dockerfile b/example/gitpod/Dockerfile new file mode 100644 index 0000000..694b6c3 --- /dev/null +++ b/example/gitpod/Dockerfile @@ -0,0 +1,17 @@ +FROM golang:1.16-alpine + +WORKDIR /app + +COPY example/gitpod/go.mod ./ +COPY example/gitpod/go.sum ./ + +RUN go mod download + +COPY . ./ +RUN go build -o /example example/gitpod/main.go + +EXPOSE 8080 + +RUN chmod +x /example + +CMD [ "/example" ] \ No newline at end of file diff --git a/example/gitpod/Jenkinsfile b/example/gitpod/Jenkinsfile new file mode 100644 index 0000000..6265f67 --- /dev/null +++ b/example/gitpod/Jenkinsfile @@ -0,0 +1,56 @@ +#!/usr/bin/env groovy + +String image_name = 'simple-go-helloworld' + +node { + docker.image('nimmis/alpine-golang').inside('-u root') { + // Preparing container + stage ('System requirenments') { + checkout scm + + // installing system required packages + sh ''' + apk add --update libltdl git make + ''' + // symlink to GOPATH and move to application workspace + sh ''' + mkdir -p $GOPATH/src + ln -s $WORKSPACE $GOPATH/src + cd $GOPATH/src/simple-go-helloworld + ''' + } + + // Run code testing + stage('Test') { + sh ''' + make test + ''' + } + + // build binary + stage('Build') { + // build the code + sh ''' + make build + ''' + } + + // deploy + stage('Deploy') { + // build image + if (params.DOCKER_REGISTRY) { + image_name = ["${params.DOCKER_REGISTRY}","${image_name}"].join('/') + } + + // build image + String short_commit = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() + echo "Building image: ${short_commit}" + echo sh(returnStdout: true, script: "docker build -t ${image_name}:${short_commit} .").trim() + echo sh(returnStdout: true, script: "docker tag ${image_name}:${short_commit} ${image_name}:latest").trim() + if (params.DOCKER_REGISTRY) { + echo sh(returnStdout: true, script: "docker push ${image_name}:${short_commit}").trim() + echo sh(returnStdout: true, script: "docker push ${image_name}:latest").trim() + } + } + } +} \ No newline at end of file diff --git a/example/gitpod/LICENSE b/example/gitpod/LICENSE new file mode 100644 index 0000000..24fd889 --- /dev/null +++ b/example/gitpod/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Aleix Penella + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/example/gitpod/Makefile b/example/gitpod/Makefile new file mode 100644 index 0000000..adf5426 --- /dev/null +++ b/example/gitpod/Makefile @@ -0,0 +1,90 @@ +# +# MAKEFILE for simple-go-helloworld + +# +# binary output name +BINARY=simple-go-helloworld + +# +# Values Version and Commit +VERSION=`cat version` +COMMIT=`git rev-parse --short HEAD || echo "unknown"` + +# +# Setup the -ldflags option for go build here, interpolate the variable values +LDFLAGS=-ldflags "-X simple-go-helloworld/release.Version=${VERSION} -X simple-go-helloworld/release.Commit=${COMMIT}" + +# +# dafault target +.DEFAULT_GOAL: all + +# define phony targets +.PHONY: clean install build docker-container docker-container-clear docker-image test dep + +# +# build the binary and deploy a container with it +all: build docker + +# +# build a clean image an container +docker: docker-image-clean docker-image docker-container + +# +# BINARY TARGETS +# + +# +# build the binary +# +# "...We’re disabling cgo which gives us a static binary. +# We’re also setting the OS to Linux (in case someone builds this on a Mac or Windows) +# and the -a flag means to rebuild all the packages we’re using, +# which means all the imports will be rebuilt with cgo disabled..." +# +# reference: https://blog.codeship.com/building-minimal-docker-containers-for-go-applications/ +# +build: clean dep + CGO_ENABLED=0 GOOS=linux go build ${LDFLAGS} -a -o ${BINARY} main.go + +# +# install compiled dependencies in $GOPATH/pkg and put the binary in $GOPATH/bin +install: clean dep + go install ${LDFLAGS} ./... + +# +# execute all tests +test: dep + go test ./... + +dep: + go get -u github.com/stretchr/testify/assert + +# +# clear binaries generated by install or build targets +clean: + if [ -f ${BINARY} ] ; then rm -f ${BINARY} ; rm -f $$GOPATH/bin/${BINARY} ; fi + + +# +# DOCKER TARGETS +# + +# +# create a docker image to run the binary +docker-image: + docker build --tag ${BINARY} --tag ${BINARY}:${VERSION} . + +# +# create a container to run the binary. +docker-container: + docker run -d --name ${BINARY} -p 80:80 ${BINARY} + +# +# clean the containers +docker-container-clean: + docker ps -a | grep ${BINARY} | tr -s ' ' | cut -d " " -f1 | while read c; do docker stop $$c; docker rm -v $$c; done + +# +# clear docker images +docker-image-clean: docker-container-clean + docker images | grep simple-go-helloworld | tr -s ' ' | cut -d " " -f2 | while read t; do docker rmi ${BINARY}:$$t; done diff --git a/example/gitpod/README.md b/example/gitpod/README.md new file mode 100644 index 0000000..8c88a7b --- /dev/null +++ b/example/gitpod/README.md @@ -0,0 +1,27 @@ +# Simple Go Helloworld +Simple Go helloworld is a web application written in Golang. +You could build and deploy the web application, on you Docker host, using the `make` utility as show below. + +```shell +make +``` + +Once `make` finishes to run, the application will be accessible at http://localhost. +![simple-go-helloworld](docs/simple-go-helloworld.png) + +## Makefile targets +- **all**: builds the application and run it on Docker host. +- **docker**: runs the application on Docker host. +- **build**: builds the application. +- **install**: installs the application and its dependencies. +- **clean**: cleans the binaries. +- **test**: runs defined test. +- **dep**: install dependency packages. +- **docker-image**: builds a docker image for the application. +- **docker-container**: creates a container and exposes it at Docker host. +- **docker-image-clean**: removes the image built for the applications. +- **docker-container-clean**: removes the containers created for the applications. + +## Authors + +Author:: Aleix Penella (aleix.penella [at] gmail.com) \ No newline at end of file diff --git a/example/gitpod/docs/simple-go-helloworld.png b/example/gitpod/docs/simple-go-helloworld.png new file mode 100644 index 0000000000000000000000000000000000000000..47eb948f7b0f1a14aac3fd44bb0bb9e18fee04e3 GIT binary patch literal 30416 zcmb@tWmucb8a7HxDWzC};?|-q?k+9vP^7q9ae_Mqin}|M;_mM5q`12Tw*UbGxbvf4f?;nmY2FZO5hK7ceMAZJ7B$oF!G&EGEDD2^zr7b-0K&!1h-5m@J zS?mJGf5lne1PJ-m@t*FkL^BFzwRcvS&Ne)f@YxI)+2<;F3#SD;6`XbQO}1na2eBc$ zhEZ247`y8@(zHGDkb++%<3NP{FfSLuC#;DzVE+>*XQfus@hq_6nqYXakdVwYR=hh{ z-Iz-9M?lZsa^{ksW?BAf(GR|}3%0-n}TYEM}I4<%q3fwh@S<C%1%Qe4Wp>G3Nug~bh!LI?err?OSUytkZ=Et+GgHe5R1XN^X&p#u|DwI{PhPo zJ8Zp@{`j#?7>0_FMdVISc6v&cpT}|%pxA}LEb#P->@@i+-_O^7n4?&aZQ>Hz@WJ}l z0g{kR=o87#)n!l>n`Yg;fi`0?Iz-F=oipGH%}PyDCxtPvT^|T)9g-6eIo+9+^q49u zct)>z!jk)@4M|L^QjODil!|hC<0tfEK&@o1RDUKJM7XcWtYQH{+w5iPNC8|pq^Me>f*%QQyVBMn~P}CFk03X>4@>Jv;R<Hu-{mT+UVZur?c?b+N=FBI z?#qVUoa*yWX3K${8r8jMS-NgMGw2+E>XT5ps@L!{$yXF765!j*>uDh(Zc!T zzM{VlnK<dM4PUefdGFQ(40bnHcRy%@ZzT&RC?94L3q z(Np60aDm}JiafINJ_`~MU2eVwr}}0z*Pkh!76CFU@ofy32OM9xo{gUqxAU}K(044~ zQlo0iZ=sOWqAl0;PD3M9o$>^I`_bVj}GlbJ8@V)nKjs zownt0_3C0i{`gm>&GU)gKFGem`pSEkOhlGiI~Xs6JaLSN6MnGG?>tv^B2yCcFDTH~ zT!}e%0nfSk_m9ETMP@|Rsn-DZK2S9M-5apE*Vw=d#igs3Oqdmd`3-Dr#Le-`_&Y%} z;~iA$QP=>Z6y= zXDpwwyvat%%QV}LZVh4O*lS29+I(s9wyi+cc>G;&Ez)D~YDA?Kh3{iqT>TLqOYM!U z+`)m$RYnC;C80TU1-Tn4X;^di>nvpB(0LVOt##Ho&p8I8$!GM8$Wa?}FPR8d4jtsp zhP@pjP`mhT2Q)ggDVln@ zhP+_SWi-)$Il`_uH3Y;jy`GY6D*nqjmk<&Md91owNLbz2td9ki^DnqiMc76CsJ0xn zk@IPzjl8r@ceRxO6|@shHX?DBb(>hP_mmla!Ow!C0qcN!%p#_&1MT(V#BaL@?p>ATq7C)k;)H4{fI%)z*!b zg}%Y-f(*B^Bo4MRE}h|xl@5K)TK4NLi8ZE`-=(|?zNRP3(1FP|o-)=7uG?f^w&?cO z_*pBAXGhvw1+p}IvZ*YxMmas3C&U6JDI`n`rErZ&>*@J^;5Q-^2m zVqcyRq0l2w$s2dH{ecZ3M*BuWmKf>71JS$f zu-jC56eY+W>jOx^SEoEi2Z})73!6}9O{07~&Mvz>c$X@ErTQuJsJXb<^XY}j8ps&3 z7tu5uE!+W3wQzj5XwMjp@y&lZ_PMvNmVTs#=vl|SQC0q%i*dB14VfWtNVq|-t# z(EETUQt~8w!N^~t2J|9CGX|4>Xhe12#;@fgzbAtEK?xqD*JPajnK<}09(()`F|i`6 zdO((%K;pk`4KG#NIKzV(l92PEJrh$_%bFg;!wvsHG@1CgY=$uI-{vNk6A_h0%cV6k zhAe=5!)t*()#w0RuWVe5!`Tg!UF~flgf`W5pe{v>Ccr@+e zYcg?MMm{8Vzzw_82w32cDJ<02iETHCBLyT6Wi6~&c&iYvU>=)JZ`L*)hdqaVMmxEq z_4UD;@FUQ_dCZKmD%Er1Fm>ptd)zee#F_5g9qwWe`6mp$?Ds<+X_; zaIBoBUXy)j%;_bY6vH)N&8DFxaL7-%8k(-65ozP*wo%`tS*|rC19$627p=ok{=qFi`iCjV~)?o3lx9COOL4MlPx0j2+kf1FJ#fzDQL+e z2-!S_8A)3$A{fu5GB_zXdeTuQ=GBy4sv78NSw((2B^UJn>6>9OSBzEhmA=^BO6KIa zbPT*X20eD2m_P05^ISF<8Dp3k@Sk^@1kuDh`ZAc!0b#j5K&abw5RF@Y5Ub5V^g}$U zqhGO$BTV@`?c>419WcNf@_9{WxeVIV(NRq!aemUGqDfwVY`mG4%hB2{opZqPCmcF9 zM9j#@aNFwkwAca3BCdOQRc*+YrD_64(?tJ-Llqym9AALV8BOe3Q1#G>Cc7vD9BCCD zXmE=rgStt*>=hWDxo=469oY3@8J{Q%2^z{*Hc+LD4o6KpFVDvR3*P%hM%ywrY^z9_Y!ye}QV(*^<~Y&+#j^F*bpn zmM7umj6?UZLD!5W!sAg#FN7EbW)eKuCmcK@hV$>BZh-&!PlLdMb~Lw!Q^iicGhE`v zc&kXS6Kg^PhTo^!`}z?3;c7zS$;Nbi;c{qZfE&Q`h_7j`BMJttuW?#lS1RRi)H!;& zAY)@CuYkW8=MQMG0I+k<3iSk$3-9U5+VMfn92_9U4%czI)=Eb$M})sg$_T~FHS7l6 z$0D|q#bxgV3EP&MaW1AYNvixNxf8Vc?%$^M*6%nvW=Rxl4v)_KaO}(AI#-;5g)kE& zi6;68;zF90p#zp?Anx$nU4LZ3Y_G5+;&rnLMO2O7SMFq}tU1)h@T<>buxx1s!>yzN z3xPerg@TeYAn5vt)n|-yq3X*tR=D!tMiVF9(c8AIoPWX)`4)Nwz{qgF;A_S$ahHAOxIWGU?1-elW$pg1p8MvM$eA{PsMToHx;GQH z)HAkDp;1pmIA0L$2$NM*GC!c>I@TDBdP_V(CRDe-L}C?7Ke9aJbOEYBQTcWUChAzm zR_GHRxq-CbjhPKL6JFlh zXYDtnFgL)4GTJ#UW*+z|0FS(rxBOCwPzryQ?5#QkV)E1VaX5EqM^oRimt z+Q5!pY8CnXq=B*_V|!^zT3Uf}`lW&`*^CpXK`m9h$uRi0ma;Z#=HLn@t`PZ-1wL0< z>Q}UhiG`^+DTU6N!DZ}w9$E@~R{={NV|iH`-c?KA<=3YlKsvb2=*dpD%F|WNb6xv! z(@%2taK(@YT3KGsQa&s6LTA1Z8sa;P$%>QHTC>Xg(ZSj@^V19+e@Kd&mlH9)8yAvh z%M&lHCG+|q`3WZQ2e84&|M3UL(Q#&*u-Ouh?*uueOWy5Fn#~j)e*Z%;v7MTn_b~WG zhuLB1gX3^-?_W66PRTFcwf}=S9h*o=Nhy5^`m>U5#tKX7iv5Tb4Qum;SNxw%C@A_J ziw_b0EJv5gi4G2|D~S^M(-UJ7{f~*rr*k7mp8-U78_@DK${|DXrFQlwb;eTMV|HZRD{txi=Kd4*Y|JTjvsB?%0 zOIRC!m)dm;M_2I>RsCS~=~5~X)2M+7`MXAG(NUjI88f_3D!M~EgTAoZ9$F829p$*) zq`l91$o~tq9ly8cOC!rh=cWc7W0q{}EU33LjP4K zw}*0cF}{-Kq*n!Kgl^Ts^eTyD&<|&5%!eHlcVGl^e864e34z)Le<>P7!J_2Ywc-;jD@GDSXaK_Q zY2fhf$C?w_3fBCva22%&i|FHJ8*Y1~8m-{|lNV})M2UPh-;YT+r&2&WjP5WzgWX;4 z0;scw0t^}4j!5-x?7DkeA4>V^Mw3}%KzJ29(g+Mdt%>_U?9lCG?~jX)p5cE} zlPAqv^hsVqPJ(hkz_*6r0t^{!<)h*Xi>&5IoPVh@^lqs+%VhQ@#j8@%4(9ivk_-)v zEf33 z*T5+>q$eAt6BEE5MT?u(BKMY9^psXv4*)QO}<*I1rf<2`u9xCxwJ z2N8JHu8rFC4mxFfVpfvANExy5E_`m|cCvinx{|VfO$wl;yrvvdPn#TnOew@N5yP#dY{uh(%~P4ijpAvX0$71J!@$ab>i2 zq>1F5eYb=-xh!OSSeVX(Z9HJaFGF?rx9`c(#5cE zI+~T`cS1dE^UV105a_4xiX}=cv5o~?(Qi4w>xo@_e4dnh#_pvffP>c|0(yP;GMqPR z=p5IJ#5NC-hlgL9FB`U=1p$XG4_y7+ZVLohkn^QM_tgLy!sD~5bmjBI`tjWS>qbc1B%gJC`eXoc$ADK^o zQ;R1|7iBi(E_%x9sXtp#gtq1?vLYXCG|F&RmbrEevOcD{hA8YvphBMA^A@I4@Q$DOdf$n`AqP1x4Ap=)g>o3=?xZ8A#3P3reE$A!!Ppo z@#7Dt3jpFU-sHq#KW|iOoow7U&AJc;UY}sCu@q5#l-mW&pCfckMFbs z?;nf*rv+D84RxOVv|!Mz39+k%F?g}oU6~lq5aE%d?+i~0*6ayfVVH`MGgHj{z;PWm zOeWi&;=VUmqm?K(y!gya=H)|h@(}SIMcB8Ju9S!UCFZZzLFuGGQ*>zb+7sfJ4)~Sp zi;3l5=jf{kaYY)Q6dZd8K7P{Kk6&5+5T<4b_#Q|}++b|$X%$F?-TqSEco>9w2}|XU zwI%E4Ttl>*r^0w>$rPN#WAVUwyRW;&${?v;web@lQ%Eo(i3Y)LX%#|(C=b=BdT)OC z0@MHADJMVMb?)l9k1he0k=eGZWNpx@Hb#v#u@m{qFOiAXv!Uoa)79vQ8e8ghVEO>6 z-=>_G+iT)&ndtS7n`f-)Of(#lNT6nzz^g+-nV3ebTwnZqP9&A-H(DOV-EXDNnDnSf z1w#oDaGu$Semgjeocu=d&gso+dt69Fwa$wAnh(Rl!Y)s8)LvD`_?J+dnxnOk^Jhww zK7LOr2)V8-qOeDT?u&E{7jdT7wEwZs%ACiTt4BhV*T&SkWN}}{+Ip4u7TdIm~%8Jxz9Tx%l2CEKHC`#BdKRmov9nsuk`Rww% z5FPl5o)Di#U60tVtKwjYf$`}oe={=t#+MYiMxGyWKuR)BfK32aY59)rOvaZ$r zOqS)dr+QWIOaSCLJzu14-wwG*CrJN2+rt+;yYQS=-;WoKRfXOMDbY5xYy;tIx{tB~ z$pg=Y2_q}+^s2>djJxsa7jST+c|V30xxHelmhUHN6#z|5%CvGFA1({fRmo2`%i|n_wWO{QT&- zQNM@WAf}-~ygS-O){nMcpNsj}fiITkh@>c` zN>?ZoJhrfH%~nLPkei;Ye3T=GVED+&rp(XmXx~0)8u7eAToY_(jZ?iE6bYWp{0KKY zqMen!tk-VbR#8hMCQgikPs+>q$W2CvmsFLvoddnh^3>lZj;`o|Vts&g0^vPxIYmX| zd*A1*Sp9<#;gKwCVbzD~Q7eSKSGKnSq+y` z?+AiOGYZOIA>mPoaM0#@b#R8ebCgI3Rb%T{NJQz+oI*2Hvv4HYEMWu*__&Qz5R#pD zCTVcs(8~MYfy)M$knbrhQ7O;D^F>N5BA>V?fe->zGe(Lj-#4q_(ouvb2clF&)+80;)$z8E?1(@`ud^A?IaH!|>ry|z}Ls5hr!qRXha zlQ)#sAr1=iNG9rhJYmOTaiggGL1w%pOKxhT{Z(2rQ~~m?YaJg4?-#_@KoN^_9hH7- zfjVn+1aRP;4s%V)C#w6X50z<$q4s6hBLTj!ns9RatJ(RAiREe&e%YK|{EviDsACSQ z6%lE({OS}2cEG55iP4QFf}>fD2CP_)*b4+6ST7DL+&Ew7fxU53e%C(7%fG*uwuSPY z(d(^nnLh&}-Lu1|rmR1OB$MApPzk(3L+@@)aTj{@5E`(tDqy>b(zd^D4?O_W8L;9T zzkBqUF&~~cfA!>={7e1#CCmNtWbm5PDY?|tvg83*i}+29wSEic`EEe-#nruQ{}{0r z)1EPd=MiN?)>sMJ)%nTLZ)xD}*LB=gNC%qNHYr1`8Tj%X7&3^s-bE(Bz0K<3DSENU zMEN5F`Jo~t_@-$}yR61YgwK+3mZoLJ1kes-U4NZF9S*vHGg}#&^ zX#w%=UTKnWTGVIgr1pML`jz zv=sx>^VZ|QocgC0!0zKkZ)X{FGN(IXaQBUI)Ra-+A#P=E;*8H=<8n`Ir4L2LN&KSd z8R?m&a5nCVLrdd{DUdUM+rc{fA1C^g=+o|q3C8v=w6G@})vaB{Su;^K@AAi8A!XBveO zZL&D#OywbgSOuT(gVHS4-%fUjlzY+tKatUp>3+U+y!+kkM>WzvapRvhq&Apeg7_x3 zCY;Z`rbP73-)g6s?tkMu_$?%CE#uPP8C}E~t-~BHl(}ryltZyX|FcSnl-ftZ9Lp$! z-3aq0D)q5$m(wN#V$xYN$r{>% zA;soWAc0RrXg2xEz)8Y}0sG9wC;5k5*MKs$z0LA9< zqM^@`iXtM?kX1FeE?-pz5=Ee(?0}u#Xp6W}9W41wb9iQ4yAdGTSh2#oe^Y|?<)3Zo zq=!+|M!(DjiGpBJdr1a32wB~_&Fnm95)wo&Zq;>uB=_~KgK5A3Rk#&~k=ve6xUY(N z3i~cWN=6oT9OB}|#-&U49v*{ibsg7BUop$4>1;h$g+zPg{kD4c^wjorNRNvb|2GMS zX3KVdluSk^bsR8gxA=AXBTtX0_HiX;Mi5`o6f`EYeY9uZ4jS*Dna-x{w54Sm4)~ca zdHGH1?P$kRUsjP@gx_Q8`Fde(T>76!Zn)~MsU1L{e@*LN*aFxUJ2=va!%N*b&rBzY zYc(3UU)D~hCviuc^=#`}D9tn^y~3-Ee!ss7xujAFH-z)Sm?py-p?Fa?k@5yrB)FxfiZ=^E$_W;S7&9p{H8|ad8nz@g%HKTZwnD_g!sS=92Be zgr>rjr#TTV!syG%ee=|N3v#|_)B*G^qk)wJ^gVfuJ_7vi5<+IyT?^DTeIZ4t2!FKM zZa8!G*qQrY*}gO)SYeGsF!kdz@U8uK{Y{Nuy*x2H;t;%iYVlmnyDc6w;{6AJPmbXP3yoP6%na3n^SwOaSeayef6}!gy zQ}_oX3rrs>8R#uzONTfagouXXjXkEiUb(p%^^LEQXpkyM%Rb*-oj#Z~uE8%Dxu1qb zwo{SaMIj-#yPv1F)|A?}Tlm7jXdHpH2HsB9&}%Y*%zS;XEEupbe*YA3zzUM0XXNT+ z`s1dYRB8gUFtkN=_EjRzqm5=Kc)EIGotIe}PZas%Nuh{c0Y5u*Ep|cj0SLZcuV3Oe z2lc~uv0u@xgRnoRA-eVaB5ywFoYLl4u=cy09xli94mouHUWr4Za!y)rh~oLU0N0%v zS;SLfaqjxgE@2LXZ!Jz%z7HErQNsA61$VsgGqMA*0bGTmf__P?WS^Li5DWv$8>^%% zr&n@x9)OQ$Z=UOPnkj0Kyf9S@;37DGpZ*d-N|^nEs^4HB`Da^Vk%Ye1ea}*n z+tm4JNde;mmz^EaEp8E8eV?)a$`3%QF;mgZg8zX)SN7s4H^4&*)1@q`aJMK6Ekdie z`rah6k=|E~WVbT2^Kv{RIi+S?3bOe=FxWpiJg{kq0Nbyw>DAYXl+kCf zr-)Y^acYy6G?xZ%t0w_(SWLX-NHdg z>>VSv@qsvZ1%RfSrg^7A{cIueuQ@_D=O6B`4@7mz2UpPlIlFRuqE?P2+d!4erZz*A zBC{Zxp*3Rel%oiQ?g)YnU@bejc@ym2 z-WX}Gpj|r#JBZzMM`sI;(cECdJzVBXqe`PVzXAiY^wyY(QBaM+-LilXI~i()8*S9g!Ikj=!m!{SeoL~8e}|6tlL&@L`68tC|2Olh}Y!rkhVe7V;hQ^_3I&HKUR zK0oz4eg2Qz5|Z#`SoGfG4XK{HN%ILOCQ$Ov3^-_jWO^sqZQwjVz9(!Yi6Ip_?mX>scgoIQyG|x8<4no7jQ8_JV ze(JS*%v9>H8+M23U^qM((%%(W7+|D8*&kqg`sHmvyxB5_? z?vI!c=PMO!&BpDWoy%h+LR9g&($Uk$B|JR%1{FxQXAV^I3JcYpHU1ohLTzAn7PoRq zukN*NA{6!`pW4SEtCSHB)mQwX{|*&&t;4AN$^DcO3xFo-<<+LE4<_YziBKt2zFn5?2P;T#@9(Ghnm9SF=E@F# z|3#1zIR^(eWK41@Ho7>b%+`&=!?13H4_p`V+^H=#gIpChUX0_FRuv%2*ykf2cA+}9 zC60lX#VE6IWX1)a1`G~HCgpRg;*Zr*QdY*^+}xz1rp6*6kt^4#AE_sgJ^Wxk6gX?S zTN&WHsWuqSRlcMOQ2pzyvy!(@_DocI@0v7O6ciLbZCbXp0cW9;jIpC%oE3`r60i0GQSlerJ-I)B{_J!xmA^8qihzlU+2VB2!#S_hTcO+9WWOoW z453yg-4%Gq6!c8`S@2nnB=V0_D0Pj!z!9^spz(9(PRVgCJUlx0pq^;+gEEol8T>jk zjBrZeL_1!p5C8e|T^fhQRu$q)WMmv{>>l{CQqt0Z1t0Me#6M({;5$7%RU?JhW`=|; zSRB;ktC9Aob>|i!e=Pp!LhWVEMQmYV(KP=X&WaWz4tAj-#&6S=R^e~`{{4Fl`GUP~ zQ+X(i+6`0!0xO$PykffhLD@fK=o7k8EeexbJb1z?CK0DmjV9#}8a643F|mw-zmb4| z01v#XI*?Q}k8S4>Sr+E@SG18()&w$#3x*ESswhR`VEzUw{16#D0Doe;w(1^CGWhG? zUmscg{^=JarT@H^Hx#Cj{jAG(AiCG&vS=%$Lg;?*PrXQm8CQBFoTVA?P`{SeD@Psd z?EIMg*0;K<8(yheQW^eOs?hQ+N zdQ zEek6vE5aY<|E0+eFK6#>mx!c`Qi2~o?^|(kF%>QCHvG`t23@nW@C&f2*Q(ZF$SWvN zt~Hal)Y$~e(kh76SdJ4-WHT?rKF!00-R}`P-30h9y0t*u5iJ^w33_U`ks=O0hA3w! zO1-m&oUVvjo*sd4czk`xX(=cVCfhypb<-&vc1wo@6fGR$iYI)Ynr`oxuTvxTrPz!W z;%*kxF{F!pT8*f+8*I0an;l(j^eb(3ZTHtA-#22m?HH@$2i8QHPh{l4i}YQ*d1zBT z9{Ny-kQ2_x_Xi@0!C;{9beSf5@B^Z`f{YO)+mlY9n5e;un;Zy>*xA{E=bcCd#QM5L zz2G}UM|p+(jv@_#$GIX#L+NtYb~CTO4;6i&R%2%O?1fZ66=r{PS#?G`UMCk8)<^i2 zYkX@AQdol-V0c5Xit#W@{|K-9nW)`0-H8&pU}z8%8@50^8bko5-ZVmx3Gzv~Ib`_1QYeUxXDJ~vaW zOFSe~ce>h`4F=&X)S04kUmvRV$A%3h{%R6XTobbrr`C0(Q(1*oV%AG^7|fev3%Lj6 zo#7`nm(+h)uh1BFrB_cpU^fS58sCK_!pj`t{uGpYP$>jVxjPUA2vm|>b`O1py7cEw@Jm!Sh3ntp z;o)7yg0#lVGh{uGBDg=9;ouOew5!ipVn`1ZaD z-KUeKdftPdh8MV*s=APAMYx7DS1Z_)F2K85=*{KvJS9QKBy|}AI3^^>1(xMi#FZq& z3FCr2RUn@;GV|;9?ry40lilTbK|0!ZRS9KMP2GaT%kz!v3Hj(A(6->KS}-Nt^-7eH zmL4W`&`+xy(ocbQD|3;D3@n`42zgSx;#T2ad%776C)T{V99XUFwfX$!PB30*F|?mx ztljvmAn^jhQ8>itcilxljfx`=FK=vIoP#*#BeI)`$sGO}Tr?;c85!3-;Uc=?3lv1~ zV)ONBjs~3nHgpLJ#3IEJwX}pQSUAu)Q7#1+PIeG58%QdzmMek&;N^YrmPjUiZ+yi2 zxJF8<3E>l5I>J_ITwi|&o0eb7Z*Sc1T61vcuEz-J99d8?UT_RzrhiPh#>e{j(=MA> zv(*r>^=U=rJ+zU=gjzLIuD&{-M&+m*K(KPjd~0jHi1mH!c&9WsF+r?-YIl^)%*-t5 zmeJ9{A*?sPIOe)MCpRePQ$LMbugl5H4-I0?3}B7~wQi)M*YI=hP^n1@U)RNz%r4|~ z!psa{Pl0;CVmZeBdxcDmdb4r0tUpB|v4>qo)eCA!X-(!Bu)Dc%e)80@_Gdn~1mTOe zgV6*mLE^zAW%`SG2~(`~n<%Bv={mxy@b`O4TOyy0Tc?(n?n zj*fN{UEiuGD09-L9)du!PEKRgC$L6FZ3lc=XGh0g;5@hMk`TJ#@sEbRgh6F;nXet`e+3+^r#E<_eSK;)yc zd7hb|mp9q%d}zg-`Q;8alC_oPGt=XD2{KfWsez{OI>eP^@&_i})gtXu$)Zl+d`Zg? z&t>W-o-P2%&Lt(h8;9yCDA&_{&5qyd@9TT3nW<$zCjo6*o%hEh6BsD+bS4nApvQtRSF+6%|6R>)|Dqy^LyEi(v>XRZ`IBsD5 zX)JaX0v?6t15Exo(0dJ_U?v(%(cWLko>Au3oS>oQz|FFIVNi zt#u6*pPaE-uCR~o-y&Axs(5YeE&9dUMeMEyS^Q{c537#HcYv1AHZ|1oEOadZtiG{r zTQyu=`PFG)kRfvm96%QBI3{C!;nF=C!0Vs=OTNxylUl+Rvx}fTv2mbdsO&q?tvK^w z%O&>cmX9rEvc0|5=jOC81)uNPWElZ}^nmetp&Dyqx!T7wmfJSqlBxHqUPlLhr;eh$ zJY#|?(j~PDm<%}Ic=fU1^@#M(3axfN?k`#^TPp7H#fZpgMKj_hM944Rbl3@dLQV>O z+C2iXAOFNWtBu00%QY8y%cR~?I_;s%!ix&4X5|NSIf(Onqh&PM9UkaV0VvDWB+ZNr zfByirl?I46gMZn?+j(QU4DpfgUTGeOi3FBuTAEy2e?fUwfoiZvB1quoN*3#{y zYEK!Ljw0o?9`Ezm6qrDNe(qy|5tNoiP~)qa_t>1+C(aHi*%mbuVNf+t*k1(I;z?Il z49`ySn0%pAR8*YE7LHDa!*ax(m)ZDtK>BzdEJEq{fk=0oDSC`%f@9KC{iN5^5fKq9 z?_o5Un0$41>TBnh!_wc#gaNJdXIo?fLERgIM(@$7^q|ru(;#9<~O1F63F7cL=LBohz=R zk4fwCR{SnwtMm1`LDQq==)nrwKZkyl#0GiaPcwS5mf4E(Z8duc7f$`$yine1>ct_? zP4zzFuCCSe<>S1{5eGYP|4B5Kge^w&&m?`$M697xer#dAj0zN}XNs$H;YC%{yggdp zO=(r!^H6z;9<=p}u52gYvzcZdOL2LtQusdNm{iH8prXxcU+JqEEtVZQ%g>d{ zPaVu_s5EMR6mYLBn=#s7T8*2#QAG3(lZ;QtbXfJf+2_w0ArVw?Kb@HCNu)J~Yo;PG zQA@7L-cN87Dy5+Caw9D$f4oQg1<>rOwUw}af|SM@VmrsQiXO?&a=yo;iJKb=MG3#o zng4zqrrH?vgNvQb7iKZF3eKTc{-e@y3ny*FGf)m zTLgc{TGhxluL^+YoQN+h=F+SV&1`&aj$SsML{nqIt0;?uJ*qTz0^>)#hCxR);fmD=18qPg&pU_QSZ$$isls0@*G9^KhC8h` zycc&OwnR{t(CIz@Wm~4r)}jCzq8TcMCP5|Xu2v=m|Vf0 zS3}!UP@SQj8@vRV5>WXi_cxTck`v=q(G?tt$l_k4bebc1drr&XI(i zy2z=2Nzq<4b82lSTx}sSKZ)Zk(^^l7ZRG5O%R9%Y#aEvv=~K=Ov+D2BfgCmS6*2-7 zb0<(sk$S2D2}k&I&!2_;Sn5$-=F1l^Sn7EZ=Q35Wb8k!|zciLtNZsx$NFFU9H8BqH z0=g<3Ut|LBvIN_%fkCBmt`$#YisFYwfo5qkb74<|pfj@aR0IMP(9SOwoV0ZV0w+ z0DU(VT_(ZY-Q8vIUS8I?EkIIL2OV*Yj*PgiUL7#B>{C2Fq?Hy|2*tyv2Y;>fu>l_| zL|ztr6Bpt@Dk{pWF~abD>cG6@_RWM@KI}_=dkF7oeR)6qun)yNAIWGuujnk=9=M0t zOV1LVsH-YB7ba(}L1hXf=+`}v;%Vf!n#;BC9?yJ*D{MNo+*oJpn0=CqxxGmAym4vd zHpV*d`3t-^`Mb_XOF23)q=@t(E%Vi;qj+ofA#_bSO3rO`YK^w5BN+fUucvRp#WBJV zV%RVEnJ;uZya!#~FN+J^fZ3f^ux;1@qxNkj`D2Q{z$|*#nJ>&!5582S6}imar8;ak zg+y}OSouSrnr!lAd+X^E?D;c-N4An2$;Jw;mb!0hpDb`yzh1@ZH3pKZ6tX(|kowkc z*mm6S@@rl(pBWqWD`ef?;NPu3qCB1D`+nM;;j_&Ei+0?lYTxy0KZW&A7GHH`9f~LwwFhD%~h_yC1kEcx#P_!0T>YxWc2b zKytcNqRiKrPSu-b|22i&Nm?0+y0nOD3maTW!MElBv-o!0mo?ect}Ry`&tdY?3I?n$q$#=DQau?)8;P6Q(y{fKxq<_`}iO!pWcVJTZ54Dor8L- zXMgbDr`s@kjD)c8B((`UYc$*Ci$iCtOv3(bZ8che4M z=?l{*lKqHR;z#QoYG@yO+Kp$d6AcgmBFr@6?% zTyawEovCJ8%L!MbZO9q?)!{m?+qVY=q=MX*{6|x%NVCDq&ll zoB-*o%G)jI-2c8Z5ZGySqzpcXxM( zLH8!l`|Xdd+WJ;%->uqOYJM;?J$?7N`t)_K)2HX2vpqj@x7f;fk1e@nmRxV-KcTig zAe6CkUhGDq)<+CS@EYDjDjftgl+XNr@w9s6qJ|&sp5x^9^~~dpVLik=_8a4cNy`;* zFpYd!OFY6(QYwzYt1ptW(sZVzTp+&y5t3-RD0Fr+C*pLH%)8zUM_2riiF)z8$hp2_ z`y4#tc07VIm)q=m!{mIfPazriZWT#d)8o-AvF_PRA(QZ#cNQQUrq4S2vgFiltsVzz za7C^zNAr(s`=d3b)wtJ2RP^+`8M4*hO0%b%FkEAeaMT5HJmwULrTKc+cDt~4)Ui!F zOQ)kAw$C?2>s#CyNgU?5W3{wf=41H`S0p73MwBrAr<>npLQK={&TpQg7wMl8M}<5jw-QU!%&yg; zU~3){US50BdPoACAb8;n%4E4bis)&#$IW35E2xC`wwaf-`Rdo7jrrI!t1SBLgwt^e zdV;bYV5gtsVvre<$$OW{hkSW`eKuzR>C+6;Cz+S07Gh1@@<#m3eh5arzI_h~+BEXZ zC%wA9wtg;9C~`i>x{o}WtNc;EyB<_$(id?Cc3prcdN>uCYj$-^GtZStbl{hM=SGc# zkH7eQwO?3zzAAt!=eV@?h`M>K9tzyv#T&Wx>FTNV@5+Q&I>E$hy7cKN=7>j-5#TjC z9FfEh5R4^7Z5W>{H~a7tQ^=&a3EtN(O*qWnSoWx~E_CY2a9Q*H*$>8Hj&@{J?}`b#`cMQfB+}Yki&L}vZfX4XzGr0V)uxua{QiCUwKLrv zPgB&}W_m0QHtRb{Y`17ID2Vq9gR(v5_m-)%giur~%loif$iDwvdF5rQziybc?`>^u}X&P-gfPO#$gK_Pk7+M^R$sd*64`x%;ObfLa z?Ene%@_TL&Wrw8f`91rKQtz_Y%_)|YiH5y|shCw3?R}30fPY}gqU|#op-XZwr z6&2|NFaw*y{z?E>$Kl@uGY_X_WOxHqgoBGO6vv>`??Wdq7d6~+oi!;K45n2sTg|JY z7Xz+2i=FWON|dNRmQ0K@KIxmuA0aG_E_x4$#Q5H29T7{iG_U|h%B2Ne}jjZ5tk+@Q3vBdegihSy1_2t44g?cC;*^;Jj}~IM z9^^0zp3Ea$k%A=cKsmwc2=~(JoO@ zWv5{!ge@`5))E+I*872ODZF@xYZmRpGQ(%^m5O2I9$R9l*h*HU%IFH6*oNUCABOgL zmYBN3oWYAP+@G|j8m2gJmw8V;J-Gw_;J9B`rZO7zfB4*Z$VBtqzCVFM=hYa;w-hmM zfqf;amtfP>2waMcK&ctrTm<=p%bLq};a6`7|KU~=;9RyrFih+GEsguwBO(A8N$94d z#Q1I83%?-4E;#{f_hDbDb=|S`oF!2MHF2vb~- zIb2*_ogWXhM(|c{h5H8v!sY`-dnQ)3pJsNal(Y=2tbPO7ay720RB)@n!or5yp1dHi zk=xXiWMvV7iot$go-o)5U zf!Bydw{%r8*H%Vc%(Dc~BytsEjh&a~!8 zy!0eTyU3CB(ocTf4A9SBHM4AV=&NV1NWgSW&`BY=7-a@?s3Y9V1if^r|82UwV8iL= zYlO6mVX8eVeaq$g*|8t+9?P$rf(Vut3M5YGkbkv)vrhW__hVuaAAWlk{Ku<+G5_=? z291*kEZUbRa(u7_|7V-Z&Yc~50;?v}qJ(3a`*&94z!5=DBOG88dnLcZzpnj?NjCbQ zVP<(E$&>#xOsbDC3jZ1~LNDL{aMQd)Cr3V@``J(aw~ab`a_p9@QCOHK^C)=JZ3P%* zYuPZ4&O6CgN5Ky_<|jWD7Q&3fBsgOp6F&TOobE`(>KLr_k3E@vjYsI6TH+(QG6v#l zi?9?}I()b};DH&E30>ayF72Si+-~(qf5S85uHQrbrG|39njs~06Mw|i+e3W2b>;HS z?Rln1u`6I6CBlmpcDU?_%N{heJg%1oeax#vN;|FY(T01!JDh8JLRTW))Veezwkmjq51gJj)VY3tB`C~hhN-z7@F2bVcp zKJDxfdgcDuym8hUIopMt+4k{v_q`KZ1ryT7sVQqh&$we~IuY5m$``$0 zycebW;u6x|{yo3C83B<27AS)Y%bB!aA7y4rAV)MKaW4E?;QIxw4kQ zv2wqrQPn;eP0HM|+PEQBdD8^{{DAtdm5K;TNvUo5==5~S>O=+wiMdCP6><4X2J&^A zt?6nm&1&FK`@FK-#3_CyH_aOFyv}NxxkK*iw8zg@>5k!I$o>?Qu%+Yj_yc~?#m;t* zp(VYU`v>=mSJOn9&Z0efk|^Y(&cmJ~D=P5mZ0)(cuR#9S&)5$WQ;-u^#g5!(uoLYH z#JsMC!T->s<)n=l{x#u>&Fz8f+BkwXjoT55(?}1(%yy8~f=D+{YsJOtd5xZQp63Qj_Kb;{gsOFWmo6|R zhPam6g1{{DxyaL&euTH>d7HlNnR8O&=a056(!0kAqF@v;|HFs3ZV*axMQN`aH;gB{ zW3QlrLhYyV2c;b>?LXh#1IOxu`;<|3xN18|)z%j0+SJ)kXlGU8D0H3zsQ34MAqU!& zZAf)l?{X?IrjdQKN)6l$1vcnNOBR~TuE^sw*FOY>tZmj?9mQ(T7_(vkT!sGEG3-ve zW^~Sq%hITyZLc6@mu}cDE916dZ3RSaq$20K+0~~bTAo9$tNo=NS}CboT(+=g4KNmu z(1)C;Pfu#T1=GG|+TC6XegXwIZOy5^a4EifL93;feM-#IS_mExsE5*Oy-PiW#Y@QA zsOi$uXtN28nshZWJ&$sA{gmxR&xRK@f$Id*}==-?m16Vz)fg)a&s}bRA_lIj` zSA)L3zZ6$}qdUJom=dgP<}m(?*7nvX^QRrQRxFBQI*n|XZ4xJ2VuoXt zx6fxw{07F<&k@BQk7TmYC+e?dxEQ+MMu+98FT%K@suDcIx?Q^cy6aADziV!zt#jzY zFM=CXyN4<=^_C&K;B7e&-c{FZK)9~Pu4Sa!f*-cs!FBR-s`NC z4WzsXyF_(1%A2>t?{=JM?feC`qt5Esg}CIB4yi0lw`#VOZofR~^!^pm2t>i;U;hBG zPOf}quY6_6;HvY4cJKyKq^UT?jeOUCx?{%M&(u}>A^>5ynRHvr0Cb2QE_@yA#NuKT z2(^FqlUiR(6A{#_6dW@$4A-9hYHH6C=c(n6?o?(6**|?tfwZO(yPpu7wC(Vx#^z36 z)+>tWc?%@N6yEi-(=VsDU#IHu+@ZMp9w3sM@XP}`2km|4Z@EoZ&qywq2b<6_lfbJL z)_9TVp}SnQ?W7AAwihwCE==$}3Pgzjsa;ivs3S{53b^ z!+&AAHVF4hF`rPrz1~sK$c3*CcXavZPA08S;)gqq`lK=P%r}w3eu0La^@dn07B+!f z0Ad4kr_owB9sC2H}m=P^)dGYL~%TlQ`;?KS* zzw)=biOh`EVsNxekm)a`3?lcD?SW$CN`~fgt7y%TWjZ*2D@{9b~e}@jE)-u zR3zRQUc!yW%+lTt-5vIf1Q(@nV>C^k4k}_GOiAnhL;0A_^baG62)sqUVUL|(6;i;X z^{+}EO^C6Jy!UOKIJE!hi;0|8q|6z%zbExBsi+i|lo^Fy?Rye*mcDY zDH=PVR0z?e0K)7q(8fQaA#c8%LaP|AjX%$IVAp(E9hA|3F0|`hth0{>gl8|0;}qvD zD~1}!gMf=q>%M3TiOjJb@ubs2Ch2DvR*$Z0-Z+^K1Y2tuoeE)*k)yXyFbgo+2KFq}(H3#ivfhhs7;!PDn({NR8i5 z)z^0Z_{K_<6AE@qducUeHmq>NaXgJgIg4^7;tc;6hH35Z@%R=)KP4dmPnICTF z)?$U|THauCAs(=HE+fQ&83zf@dT$zt@Rud>yT4yGuEkWY=Av%x%rspubsi8tf8B$8 zht_m|Jq@OP_D(zZJ-tcwsUhk(o;!W=dq_$|{OsRss{KfOSAPGkuJ}Dq!r(L4jmzy! zp-!jjY&oSC2FLTmPr|Dcg0WWf(~WAY?>e}?tq-h8N}F_-P&Xy)ob*}VX9STMp_g1Y z9i(9$!l7fs|Kl2*t(wBu2o|X}vW! zMJ=}_T0AqT+lq0sUmwgq4a|nKIA0_<-53(OAK0; zaZu(gNWMv`)f?t)!zv3MWa<3}?q~)Qk7k+6i`(ri`HN%x!fg$D*8b|0^btgeQ}SA) zHs_r-CYQpduS$=N8__LOSE7!^8%dcCy1q4g?u83zAj29r?s^fg$*`K%x4;h*APiq`{;Wa{YwJX9yE7MZIR1%2 zbse^ynVpYLYu{$Suz2hT zo%T+jfsVt0$oX1f64wx6;pWLSb_!itv>^sxd`%ql(UYKk{Fd{zbO@zm)!eCn15z0n#yR;|G0F9f~6Ui95iT zVhH^R|B3#mKtchMt`q5(*1%)DukAnk#0v%gZT!EOT>MYuA^%y^w2F--=oh`LuZ?%} zFyN@Xg34U-M8+o58n)$Vp-nVVx4%I|j>gmd*q5y`H7z|8LwL;?zK^(XRA)h$E^yLY zQ*vKdYRkQFucLdVjy^M4p|3fmV*yidZo0d>tG{#sKGZ{C{wyiyIz&Pu;8)4`HZt<L^i>J7^gn^+h%OCfmtCk~4Vo!)Q zifhZy_l_>N)Y4BNxsWmQVmpJMNjf+N2BafKo`d_W?w4-A!9mp%0}VBp$KaxOIj=5H z^gBBp$81(uVY^NEfvKhBdSSx|X}ff4em)}Nf>6lP0#x&yn_1r?-tA<_h4&I4ioSBQ z3F5uy{vV?C%)WO^#Vh(-7ofd;Nn4>MF8;4I>9NPx{&R2Thg)O(4lv(|*G{<2Ok7&3 z3vgoTY34)@A3^O{U5V_ge3%y&IY{QJxo}prHzU(z3zNO%L@PQ3mG zwx&~(q_=Bi8%nsJulEp;8JnO+9G9+19G1HG6#rcJl&Ow|7_I^a)pFM*w@`w_=if(jHv8}ti!^Tr8{?R$?9%q9Rt6@v< zw!!E`xicmOELoHyao%uHr>hwFy3~=h@Z>=I$}f2{h>9kj@fpFyr1T^1e0#yRnzPd< zwM9EDtvh~lEVtF~>TEPU-3mu`cILV}JaNk0{+jcY z$FNm)zQMfCo+;PUCam-}i(C-Baqy(-ie&6CXlqjCxr$fy`z2l(FWGXkL#E8oj1&+d znbN6u!!y!i#}@D9EI3dAFGJ)$>#n^3hK$16T>iehP95L_*cyqpFyH}|92%IQa%c~Z9m3(mE@Df#QmLsYd~c^OLe z7`+W{y2WaqXHW1}l=z)%&FN+{oxbsA_ZtPION&e_PinvOo{9p7XtVTI54bt#fY);r zjUfb(ui9yiA=^EyW1Sy{>#g2a&veDRw?*E;bP6y>)m)!wi-i7s)lX|WpPCgGIN185 z&uas{U^^)&RyGl-@{YHqbK)^L-3eqcf%Q$TcGr{6l^O41&1}mq$NwX5F&|Cs790_U zB9pb2`{BuA_=W(oM1WK7XF%cb+n@ksn)O~YptlLT+{kHCtFsVmMY1!*e$i<|L6U|x z(ME+E`O1EB<<_A9`fegCXox)FfE+8OGZ+WU>X9bt<>Aqd3S9?y^^k-&zN5Bg*$W&-jfc3$#v?bmobEzApN7o!72H!^ z4cG6Jx@}iVv49^;hM{|Nc9+*A3t#ww`uUg+0A##CU$N*k0Q^ba$qY6x4)v*@mwY_mdiKKYC!BW{j7ApCDyz!y;Vq;J4lL2m{wbhMS>Xj zhoa^(du|qSqUYcPoS!S>Q9;<~?>LnBsj9{6k07?93=keEnwZVd8>(Z?*2tdY2hK2p z(YE&5Mh?~z=`qy7I^8kTUBfnqilxPgiU_)UPvf9^3$dq4oZ0eF^LwamE1{-S96zjY z&wK0!#Fk?(i&^4j41#@#?;}oOfX9S=1dT{at&_TZM11hnWepP5h_q zV8V+WuHNAmT0BRj-|$LkjmMd8+M1La2M)grf1#(={tR_Z1@22!AdDHdJ#J?{4>zd& zjh1VBH<(HkG-old>fYt&o_5D?kw?VX%vZvul?-C+>V24Gc;U0I9fCxF-NcG^ht%6Z zORp;VN`>y`?wM1&OVhlr}RMlTfrUzibH8|)H}BJ=1DL)lyrz_DVoA6pZVji z4#`AV;e52y*b-6EXma0w{#jx5+x!RGwsB2lCL3ErKWpke%I|}rZQ zdW#MyzOyE)RAxxt{CN>Dlw>y*Z4wuHDxs13Bng6$a$ARQtk) zIYuZTY%9;eF(f;$G0l#N4a~Imnb#JlF*5^i*g5c^@)^+btZzxf9Euvu!bv852_h|( z;g$zA7d7UFh!QUKf_k*!1fodlrLPF^^|X8`Jlwa__!iaLag8+D~SmXL71F+q?iA@!u1wvAQN@Y|5D z-O?2cSWVI9AXf4Cq$di|RQVmOvY>8v=VB|E5_RR8{F;r~`tuBJU})VM!N)ZGi_I~ zLk6l_Ja>ROY~=|Yu^KW0M_hgxZKoM{khUo-hD@gCi>`eRb%)L&TAa@~$W>BCnsmr) zv_Fok9`P6*&yZOrQG82u(Ak#T*6XJv2QB%o76*V}Zcod;S`LBs%ke-~XpU*KDRO|F z9ZT+4dJ4@C?!{oc@G7L=Orm;^IFQ4j_q5==G9)1^KLzXs?FlmLSXo(}Iyt^bn3sn% ztm40KkN)3OBrs0OG7k06-|HnTW0_eJWtkUsJnmH;vY&jHzqbnSNIy-oH1tJ~RHq}H z{mOiAJn_eTe$do7qdOc>;iKgErx>t7Caxh6e7r5~M>>U{ALGD}jNBz4GHvo{PF%?} zf^-pFHOaKEno*Tqq2Gwx$MR(~2B%r2rZ9fKtFazro&aPSe*Y9daM{A=g>{$c>`=%H z>MasL9W0YVyJq6(A%X#d8Dxp)>82%_enwnkwD=^`vr?ZYq`_R`EV$(8h3WMmk&?<3 zK`B?v@YUxAVjCC0yuqm&cSYf6ma&qz41NM|1J1%1C_$->?3 z*YC{&D^cYf$Enz3 z)h(`OvD-d3&mv{9cbG`t|2Q@$Xo>(oGoE6Sd+o``BElL?j*o~%ttsF`N?Z~DQ%*^j zrKWm3jztQf2e^L|bD|`;u^XGf&O6U$QD6}2B<#KKqW3e*9CBa9GlrTVyF6F3*$6pJG&Wj+U z!u}VyG*M~g6ap9LTUqEKWSzvi)z;%fLv{vU>R3`|?8q8$ygyPi8yTfDFe0v`s;Va6 zi#b+;QTg6j76pY{7?VcBRA^LH{Ro^9?Aa9!mE`PfugnxSHA%}PUx~E?jM0cL~b{*hsy@Mea|l#8B&!SHk58l@I}ysv)2G*lxIqTp}){p zoNHVd_WrF%fZ%(U*PQt*bb$|yrNNec7isc~ zQK!QPrbTziSX?7k1GCD!M4M?7}Z%pB8{ny*&!T_mfoPM$UKPWX54y8c5GiiMgD;&r;hrcA>51b?SFu z86D-G6eiv4hMlj>j@@a9ofu6?XvU9W8%=2;JM%rHTX|RUTd4m;N-% z32{;*2+^n)sPQJHA`IFPkI0IQ z{A=*mW<$(al6hKjy`K^MM@e00khzo?Ka{?ar6hXDCe5iy%uXSWEkU*5M)f4wdKU>A zdI%lM6h&YUiJ+;fDBMyGKyZ&sZjI^jxoj-o)n=qA{?b{o=*LKjYFWH6^pM~p*un9+ zC|da*WV(^?W6Af$h2)s8I^OQ$w|n!lo)jbXIUM;D>0^A zn&bP>Yfz~#pwp2)J|K_|uT!yU1I1zE0}rzoiemExxvP_}DyCbRt$3-P@lNiL%fFC0 z^9*+W2F`*?HL+2w#x1q5qf;;X*oa)IHh3QXo%Hzl+*iG-%X7IS{N=i^Dd}=sx@F-lh^6Wq;z!lkS8BqvdrIo+bCmCy9Y&+_TTTC{CMxT?^tz* z2E_a%v|`B@`m&9RgLZm&@hKE%gk6fZ$h&QeUeKLL{0CkAhQ_`>rU5`46PE(>Xb)9Q zjg2Zuh;V8RVVf3br!&I=EKNdta7ZyVC3u}U@Rt504KyXD(GVZ=0lF4Cu3f8!#b)h6 zcz(eo(8ttRruw_9Y#!Y20e-MZf?WYH>D*Ep92ErrE%%GCpph@l3-bsZrDdCf;w59u zL}0Eo?Cr8H6hhNuC^(s^67c5pjg3hhMy&BGGPrhKiRy=7sQY23?*v5AF7`;<|^aGqi-nOG1E=;$mxCG zzxcE)U9$fo3U1#vx~55nP3?u>Vkg>`WM~^|02UfjE=V6H%+g!g~_jxX0>CD z2oMhJHchUmozGe28F=-7J$*h`WBO8=-S>C;C3z93}f(}tS^Cfe^goC|2^K>f3 z!#rYiIw~9bMBSZa6kUVoY64#I&JH zI$f6M5a}DsC70C#)B=9!s24AgcYW;g9cU2Eo$xLFK!E(M*EfLvfGl|^V$Xykd*_~GvE_bbtC%gsH~=k@=v@gdEOtTp3I25zae>m15~ojL8BiMBmC9SM(mMJ`Ak zO;`T#?tKH{a2=4&Sgu89m=Dr(YYOoKmFmpbi(DvTUkTfuX)np!IEbS*z z>v8R%8l-8shdv|qHsvVzzG}xrzF{?z;0QZD=C7_6~@SPTNQ!RG`Cg$hZbTDDEV;UqJ)N2N5k(u%;QU+X?t}F# zH3VCgoCRY#732i0VhMhcwaS5PqXQo&E;$>BGK%4%1h^%0*vwC+no*oZztWHCZ1U=wax#25M4!#s3_}F<$i5WwEabFSh*1YK-_O z&$QDIs|t$UDcl0|&R!8Yjs~nxAY08?4ANKNhYLs}KK4i@63&VlOU-GmL-#>WpbF({?w9G^R#f_*{=`JlD6b`%5p_c_t^_nHQ><;jAwGeeQ|X*g6t8RMCtILX=a-)360V}3vUI!lZGddjn#Y# zH%fBCAIAy6(n!gaSFr2*84~2Ukv_t o9%cLgX8nHz{vSnP^chu+ZCc)nY5pAeNm?i|A!)%9er@mn0*=&{m;e9( literal 0 HcmV?d00001 diff --git a/example/gitpod/go.mod b/example/gitpod/go.mod new file mode 100644 index 0000000..6221f79 --- /dev/null +++ b/example/gitpod/go.mod @@ -0,0 +1,3 @@ +module github.com/apenella/simple-go-helloworld + +go 1.12 diff --git a/example/gitpod/go.sum b/example/gitpod/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/example/gitpod/main.go b/example/gitpod/main.go new file mode 100644 index 0000000..5ae43e2 --- /dev/null +++ b/example/gitpod/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "html/template" + "net/http" + "os" +) + +type Context struct { + Version, Commit, Hostname string +} + +func helloworld(w http.ResponseWriter, r *http.Request) { + var hostname string + var err error + + hostname, err = os.Hostname() + if err != nil { + hostname = "unknown" + } + + context := Context { + Hostname: hostname, + } + + page := ` + + + Simple Go Helloworld + + + + + +
+

Simple Go Helloworld

+

I'm {{.Hostname}}

+
Version: 1
+
+ + + ` + + t := template.New("Simple Go Helloworld") + t, _ = t.Parse(page) + t.Execute(w, context) +} + +func main() { + http.HandleFunc("/", helloworld) + http.ListenAndServe(":80", nil) +} \ No newline at end of file diff --git a/example/gitpod/main_test.go b/example/gitpod/main_test.go new file mode 100644 index 0000000..169cae1 --- /dev/null +++ b/example/gitpod/main_test.go @@ -0,0 +1,33 @@ +package main + +import ( + "net/http" + "net/http/httptest" + "testing" +// "strings" + "github.com/stretchr/testify/assert" +) + +func TestHelloword(t *testing.T) { + // Create a request to pass to our handler. We don't have any query parameters for now, so we'll + // pass 'nil' as the third parameter. + req, err := http.NewRequest("GET", "/", nil) + if err != nil { + t.Fatal(err) + } + + // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response. + rr := httptest.NewRecorder() + handler := http.HandlerFunc(helloworld) + + // Our handlers satisfy http.Handler, so we can call their ServeHTTP method + // directly and pass in our Request and ResponseRecorder. + handler.ServeHTTP(rr, req) + + // Check the status code is what we expect. + expected_status := http.StatusOK + assert.Equal(t,rr.Code,expected_status,"handler returned wrong status code: got %v want %v",rr.Code, expected_status) + + expected_text := "Helloworld" + assert.HTTPBodyContains(t, helloworld, "GET", "/", nil, expected_text ,"handler returned wrong status code: got %v want %v",rr.Code, expected_text) +} \ No newline at end of file diff --git a/example/gitpod/version b/example/gitpod/version new file mode 100644 index 0000000..ceab6e1 --- /dev/null +++ b/example/gitpod/version @@ -0,0 +1 @@ +0.1 \ No newline at end of file