Skip to content

Commit 203303a

Browse files
committed
Initial
1 parent 1ac7d60 commit 203303a

File tree

2 files changed

+205
-0
lines changed

2 files changed

+205
-0
lines changed

GitHubUpdater/Task.cls.xml

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Export generator="Cache" version="25">
3+
<Class name="GitHubUpdater.Task">
4+
<Super>%SYS.Task.Definition</Super>
5+
<TimeCreated>63603,50211.569893</TimeCreated>
6+
7+
<Parameter name="TaskName">
8+
<Default>GitHub Update</Default>
9+
</Parameter>
10+
11+
<Property name="GitHubURL">
12+
<Description>
13+
Repository URL, like https://github.com/intersystems-ru/Cache-MDX2JSON</Description>
14+
<Type>%String</Type>
15+
</Property>
16+
17+
<Property name="Username">
18+
<Description><![CDATA[
19+
GitHub user, who has access to repository. Optional for public repositories.<br>
20+
Note, that with Username/Password, you can make up to 5,000 requests per hour.
21+
For unauthenticated requests, the rate limit allows to make up to 60 requests per hour.
22+
Unauthenticated requests are associated with an IP address.<br>
23+
Required, if you want to create webhooks]]></Description>
24+
<Type>%String</Type>
25+
</Property>
26+
27+
<Property name="Password">
28+
<Description>
29+
GitHub password, corresponding to Username. Optional for public repositories.</Description>
30+
<Type>%String</Type>
31+
</Property>
32+
33+
<Property name="Namespace">
34+
<Description>
35+
Namespace, where to download and compile repository</Description>
36+
<Type>%String</Type>
37+
<InitialExpression>$Namespace</InitialExpression>
38+
</Property>
39+
40+
<Property name="Branch">
41+
<Description>
42+
Repository branch, usually master. Leave empty, if you want to receive default branch.</Description>
43+
<Type>%String</Type>
44+
<InitialExpression>"master"</InitialExpression>
45+
</Property>
46+
47+
<Method name="OnTask">
48+
<ReturnType>%Status</ReturnType>
49+
<Implementation><![CDATA[
50+
Return:'##class(%SYS.Namespace).Exists(..Namespace) $$$ERROR($$$NamespaceUnavailable,..Namespace)
51+
52+
Set Owner = $p(..GitHubURL,"/",4)
53+
Set Repository = $p(..GitHubURL,"/",5)
54+
55+
Return ##class(CacheGitHubCI.Hook).Update(Owner, Repository, ..Branch, ..Username, ..Password, ..Namespace)
56+
]]></Implementation>
57+
</Method>
58+
59+
<Method name="Update">
60+
<Description><![CDATA[
61+
Downloads and compiles GitHub repository.<br>
62+
<b>Owner</b> - The name of the repository owner.<br>
63+
<b>Repository</b> - The name of the repository.<br>
64+
<b>Branch</b> - The name of the commit/branch/tag. If skipped the repository’s default branch (usually master) would be used.<br>
65+
<b>Username</b> - GitHub user, who has access to repository. Optional for public repositories.<br>
66+
<b>Password</b> - GitHub password, corresponding to Username. Optional for public repositories.<br>
67+
Note, that with Username, you can make up to 5,000 requests per hour.
68+
For unauthenticated requests, the rate limit allows to make up to 60 requests per hour.
69+
Unauthenticated requests are associated with an IP address.<br>
70+
<b>Namespace</b> - Namespace, where to download and compile repository.<br>
71+
72+
For example in the repository: https://github.com/intersystems-ru/Cache-MDX2JSON<br>
73+
Owner - intersystems-ru, Repository - Cache-MDX2JSON.<br> ]]></Description>
74+
<ClassMethod>1</ClassMethod>
75+
<FormalSpec>Owner:%String,Repository:%String,Branch:%String="",Username:%String,Password:%String,Namespace=$Namespace</FormalSpec>
76+
<ReturnType>%Status</ReturnType>
77+
<Implementation><![CDATA[
78+
Set req = ..CreateRequest(Username, Password)
79+
Set req.Location = "repos/" _ Owner _ "/" _ Repository _ "/contents" // as described in https://developer.github.com/v3/repos/
80+
Do:(Branch'="") req.SetParam("ref",Branch) // if omitted the repository’s default branch (usually master) would be used
81+
82+
Set links = ##class(%ListOfDataTypes).%New()
83+
Set st = ..ProcessDirectory("",req,.links)
84+
Return:$$$ISERR(st) st
85+
86+
Set namespace = $Namespace
87+
Zn Namespace
88+
Set st = ..DownloadFiles(links,req,.list)
89+
Set st2 = $system.OBJ.CompileList(.list,"cuk /checkuptodate=expandedonly")
90+
Zn namespace
91+
92+
Return $$$ADDSC(st, st2)
93+
]]></Implementation>
94+
</Method>
95+
96+
<Method name="ProcessDirectory">
97+
<Description><![CDATA[
98+
Process one directory of GitHub repository. Recursive.<br>
99+
<b>Path</b> -Internal repository path. Root is empty string<br>
100+
<b>Request</b> - Authenticated/Set %Net.HttpRequest object.<br>
101+
<b>Links</b> - List of links to raw files (which satisfy <b>IsCacheFile</b> conditions) from repository.<br>]]></Description>
102+
<ClassMethod>1</ClassMethod>
103+
<FormalSpec><![CDATA[Path:%String="",Request:%Net.HttpRequest,&Links:%ListOfDataTypes]]></FormalSpec>
104+
<ReturnType>%Status</ReturnType>
105+
<Implementation><![CDATA[
106+
Set location = Request.Location
107+
Set Request.Location = Request.Location _ Path
108+
109+
Set st = Request.Get()
110+
Return:$$$ISERR(st) st
111+
Return:(Request.HttpResponse.StatusCode = 404) $$$ERROR($$$GeneralError,"Repository doesn't exist OR you don't have access")
112+
Return:((Request.HttpResponse.StatusCode = 403) && (Request.HttpResponse.GetHeader("X-RATELIMIT-REMAINING")=0)) $$$ERROR($$$GeneralError,"API rate limit exceeded. Try logging in.")
113+
Return:(Request.HttpResponse.StatusCode '= 200) $$$ERROR($$$GeneralError,"Received " _ req.HttpResponse.StatusCode _ " expected 200")
114+
115+
#dim objects As List of %ZEN.proxyObject
116+
#dim obj As %ZEN.proxyObject
117+
Set st = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(Request.HttpResponse.Data,,.objects,1)
118+
Return:$$$ISERR(st) st
119+
120+
For i = 1:1:objects.Count() {
121+
Set obj = objects.GetAt(i)
122+
If (obj.type = "dir") {
123+
Set st = ..ProcessDirectory("/"_obj.name,Request,.Links)
124+
Return:$$$ISERR(st) st
125+
} ElseIf (obj.type = "file") {
126+
Do:..IsCacheFile(obj) Links.Insert(obj."download_url")
127+
} Else {
128+
// obj.type = "symlink" or obj.type = "submodule"
129+
}
130+
}
131+
Set Request.Location = location // to keep track of where in the repository tree we are
132+
Return $$$OK
133+
]]></Implementation>
134+
</Method>
135+
136+
<Method name="IsCacheFile">
137+
<Description>
138+
Check that incoming file is the one you need.</Description>
139+
<ClassMethod>1</ClassMethod>
140+
<FormalSpec>File:%ZEN.proxyObject</FormalSpec>
141+
<ReturnType>%Boolean</ReturnType>
142+
<Implementation><![CDATA[
143+
Set extensions = ",xml,cls,csp,csr,mac,int,bas,inc,gbl,prj,obj,pkg,gof,"
144+
Return:($L(File.name,".")=1) 0 //no extension
145+
Set File.Extension = $P(File.name,".",$L(File.name,"."))
146+
Return $F(extensions,","_File.Extension_",")
147+
]]></Implementation>
148+
</Method>
149+
150+
<Method name="DownloadFiles">
151+
<Description><![CDATA[
152+
Download list of files on https://raw.githubusercontent.com/ server.<br>
153+
<b>Links</b> - List of links to raw files.<br>
154+
<b>Request</b> - Authenticated/Set %Net.HttpRequest object.<br>
155+
<b>loadedlist</b> - Returns an array of the items loaded. ]]></Description>
156+
<ClassMethod>1</ClassMethod>
157+
<FormalSpec>Links:%ListOfDataTypes,Request:%Net.HttpRequest,*Items</FormalSpec>
158+
<ReturnType>%Status</ReturnType>
159+
<Implementation><![CDATA[
160+
Kill Items
161+
Set Request.Server = "raw.githubusercontent.com"
162+
Set st = $$$OK
163+
164+
For i = 1:1:Links.Count() {
165+
Set streq = Request.Get($e(Links.GetAt(i),35,*)) // Remove "https://raw.githubusercontent.com/" from URL.
166+
Set:$$$ISERR(streq) st=$$$ADDSC(st, streq)
167+
Set stload = $system.OBJ.LoadStream(Request.HttpResponse.Data,"",.error,.items)
168+
Set:$$$ISERR(stload) st=$$$ADDSC(st, stload)
169+
Merge Items = items
170+
}
171+
172+
Set Request.Server="api.github.com"
173+
Return st
174+
]]></Implementation>
175+
</Method>
176+
177+
<Method name="CreateRequest">
178+
<ClassMethod>1</ClassMethod>
179+
<FormalSpec>Username:%String,Password:%String</FormalSpec>
180+
<ReturnType>%Net.HttpRequest</ReturnType>
181+
<Implementation><![CDATA[
182+
Set namespace = $Namespace
183+
Set SSLConfig = "GitHub"
184+
185+
Zn "%SYS"
186+
Do:'##class(Security.SSLConfigs).Exists(SSLConfig) ##class(Security.SSLConfigs).Create(SSLConfig)
187+
Zn namespace
188+
189+
Set req=##class(%Net.HttpRequest).%New()
190+
Set req.Https=1
191+
Set req.SSLConfiguration=SSLConfig
192+
Set req.Server="api.github.com"
193+
Do req.SetHeader("Accept","application/vnd.github.v3+json") // we want 3rd version of api
194+
195+
If ($d(Username) && $d(Password) && (Username'="") && (Password'="")) { // supply Username and Password, if both are provided. GitHub accept Basic Auth
196+
Set req.Username = Username // https://developer.github.com/v3/auth/
197+
Set req.Password = Password
198+
}
199+
200+
Return req
201+
]]></Implementation>
202+
</Method>
203+
</Class>
204+
</Export>

sc-list.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GitHubUpdater.Task.CLS

0 commit comments

Comments
 (0)