1
1
const Core = require ( "@actions/core" ) ;
2
2
const ToolCache = require ( "@actions/tool-cache" ) ;
3
3
const Octokit = require ( "@octokit/request" ) ;
4
+ const fetch = require ( "node-fetch" ) ;
4
5
const Path = require ( "path" ) ;
5
6
const ChildProcess = require ( "child_process" ) ;
6
7
const Util = require ( "util" ) ;
7
8
const FS = require ( "fs" ) . promises ;
8
9
10
+ const exec = Util . promisify ( ChildProcess . exec ) ;
11
+ const execFile = Util . promisify ( ChildProcess . execFile ) ;
12
+
9
13
async function run ( ) {
10
14
try {
11
15
const params = { } ;
@@ -24,6 +28,10 @@ async function run() {
24
28
throw `Platform "${ getPlatform ( ) } " is not supported` ;
25
29
}
26
30
await func ( params ) ;
31
+
32
+ Core . info ( "[command]crystal --version" ) ;
33
+ const { stdout} = await execFile ( "crystal" , [ "--version" ] ) ;
34
+ Core . info ( stdout ) ;
27
35
} catch ( error ) {
28
36
Core . setFailed ( error ) ;
29
37
process . exit ( 1 ) ;
@@ -69,7 +77,7 @@ async function installCrystalForLinux({
69
77
arch = getArch ( ) ,
70
78
destination = null ,
71
79
} ) {
72
- checkVersion ( crystal , [ Latest , NumericVersion ] ) ;
80
+ checkVersion ( crystal , [ Latest , Nightly , NumericVersion ] ) ;
73
81
const suffixes = { "x86_64" : "linux-x86_64" , "x86" : "linux-i686" } ;
74
82
checkArch ( arch , Object . keys ( suffixes ) ) ;
75
83
@@ -86,13 +94,12 @@ async function installCrystalForMac({
86
94
arch = "x86_64" ,
87
95
destination = null ,
88
96
} ) {
89
- checkVersion ( crystal , [ Latest , NumericVersion ] ) ;
97
+ checkVersion ( crystal , [ Latest , Nightly , NumericVersion ] ) ;
90
98
checkArch ( arch , [ "x86_64" ] ) ;
91
99
return installBinaryRelease ( { crystal, suffix : "darwin-x86_64" , destination} ) ;
92
100
}
93
101
94
102
async function installAptPackages ( packages ) {
95
- const execFile = Util . promisify ( ChildProcess . execFile ) ;
96
103
Core . info ( "Installing package dependencies" ) ;
97
104
const args = [
98
105
"-n" , "apt-get" , "install" , "-qy" , "--no-install-recommends" , "--no-upgrade" , "--" ,
@@ -105,20 +112,28 @@ async function installAptPackages(packages) {
105
112
}
106
113
107
114
async function installBinaryRelease ( { crystal, suffix, destination} ) {
108
- if ( crystal === Latest ) {
109
- crystal = null ;
115
+ let path ;
116
+ if ( crystal === Nightly ) {
117
+ path = await downloadCrystalNightly ( suffix , destination ) ;
118
+ } else {
119
+ if ( crystal === Latest ) {
120
+ crystal = null ;
121
+ }
122
+ path = await downloadCrystalRelease ( suffix , crystal , destination ) ;
110
123
}
111
- const path = await downloadCrystalRelease ( { suffix, tag : crystal , destination} ) ;
112
124
113
125
Core . info ( "Setting up environment" ) ;
114
126
Core . addPath ( Path . join ( path , "bin" ) ) ;
115
127
}
116
128
117
- async function downloadCrystalRelease ( { suffix, tag = null , destination = null } ) {
129
+ const GitHubApiBase = "/repos/crystal-lang/crystal" ;
130
+ const CircleApiBase = "https://circleci.com/api/v1.1/project/github/crystal-lang/crystal" ;
131
+
132
+ async function downloadCrystalRelease ( suffix , tag = null , destination = null ) {
118
133
Core . info ( "Looking for latest Crystal release" ) ;
119
134
120
135
const releasesResp = await githubGet ( {
121
- url : "/repos/crystal-lang/crystal /releases/" + ( tag ? "tags/" + tag : "latest" ) ,
136
+ url : GitHubApiBase + " /releases/" + ( tag ? "tags/" + tag : "latest" ) ,
122
137
} ) ;
123
138
const release = releasesResp . data ;
124
139
Core . info ( "Found " + release [ "html_url" ] ) ;
@@ -133,14 +148,47 @@ async function downloadCrystalRelease({suffix, tag = null, destination = null})
133
148
return onlySubdir ( await ToolCache . extractTar ( downloadedPath , destination ) ) ;
134
149
}
135
150
151
+ async function downloadCrystalNightly ( suffix , destination = null ) {
152
+ Core . info ( "Looking for latest Crystal build" ) ;
153
+
154
+ let build ;
155
+ for ( let offset = 0 ; ; ) {
156
+ const req = `/tree/master?filter=successful&shallow=true&limit=100&offset=${ offset } ` ;
157
+ const resp = await fetch ( CircleApiBase + req ) ;
158
+ const builds = await resp . json ( ) ;
159
+ build = builds . find ( ( b ) => b [ "workflows" ] [ "job_name" ] === "dist_artifacts" ) ;
160
+ if ( build ) {
161
+ break ;
162
+ }
163
+ offset += builds . length ;
164
+ if ( offset >= 1000 ) {
165
+ throw "Could not find a matching nightly build" ;
166
+ }
167
+ }
168
+ Core . info ( "Found " + build [ "build_url" ] ) ;
169
+ Core . setOutput ( "crystal" , build [ "vcs_revision" ] ) ;
170
+
171
+ const req = `/${ build [ "build_num" ] } /artifacts` ;
172
+ const resp = await fetch ( CircleApiBase + req ) ;
173
+ const artifacts = await resp . json ( ) ;
174
+ const artifact = artifacts . find ( ( a ) => a [ "path" ] . endsWith ( `-${ suffix } .tar.gz` ) ) ;
175
+ Core . info ( "Found " + artifact [ "url" ] ) ;
176
+
177
+ Core . info ( "Downloading Crystal build" ) ;
178
+ const downloadedPath = await ToolCache . downloadTool ( artifact [ "url" ] ) ;
179
+
180
+ Core . info ( "Extracting Crystal build" ) ;
181
+ return onlySubdir ( await ToolCache . extractTar ( downloadedPath , destination ) ) ;
182
+ }
183
+
136
184
async function installCrystalForWindows ( {
137
185
crystal = Nightly ,
138
186
arch = "x86_64" ,
139
187
destination = null ,
140
188
} ) {
141
189
checkVersion ( crystal , [ Nightly ] ) ;
142
190
checkArch ( arch , [ "x86_64" ] ) ;
143
- const path = await downloadCrystalForWindows ( destination ) ;
191
+ const path = await downloadCrystalNightlyForWindows ( destination ) ;
144
192
await setupCrystalForWindows ( path ) ;
145
193
}
146
194
@@ -169,7 +217,6 @@ const outputSep = "---";
169
217
const vcvarsPath = String . raw `C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat` ;
170
218
171
219
async function variablesForVCBuildTools ( ) {
172
- const exec = Util . promisify ( ChildProcess . exec ) ;
173
220
const command = `set && echo ${ outputSep } && "${ vcvarsPath } " >nul && set` ;
174
221
Core . info ( `[command]cmd /c "${ command } "` ) ;
175
222
const { stdout} = await exec ( command , { shell : "cmd" } ) ;
@@ -197,11 +244,11 @@ function* getChangedVars(lines) {
197
244
}
198
245
}
199
246
200
- async function downloadCrystalForWindows ( destination = null ) {
247
+ async function downloadCrystalNightlyForWindows ( destination = null ) {
201
248
Core . info ( "Looking for latest Crystal build" ) ;
202
249
203
250
const runsResp = await githubGet ( {
204
- url : "/repos/crystal-lang/crystal /actions/workflows/win.yml/runs?branch=master&event=push&status=success",
251
+ url : GitHubApiBase + " /actions/workflows/win.yml/runs?branch=master&event=push&status=success",
205
252
"per_page" : 1 ,
206
253
} ) ;
207
254
const [ workflowRun ] = runsResp . data [ "workflow_runs" ] ;
@@ -211,7 +258,7 @@ async function downloadCrystalForWindows(destination = null) {
211
258
212
259
const fetchSrcTask = async ( destDir ) => {
213
260
const zipballLinkResp = await githubGet ( {
214
- url : "/repos/crystal-lang/crystal /zipball/:ref",
261
+ url : GitHubApiBase + " /zipball/:ref",
215
262
"ref" : ref ,
216
263
request : { redirect : "manual" } ,
217
264
} ) ;
@@ -227,13 +274,13 @@ async function downloadCrystalForWindows(destination = null) {
227
274
228
275
const fetchExeTask = async ( ) => {
229
276
const artifactsResp = await githubGet ( {
230
- url : "/repos/crystal-lang/crystal /actions/runs/:run_id/artifacts",
277
+ url : GitHubApiBase + " /actions/runs/:run_id/artifacts",
231
278
"run_id" : runId ,
232
279
} ) ;
233
280
const artifact = artifactsResp . data [ "artifacts" ] . find ( ( x ) => x . name === "crystal" ) ;
234
281
235
282
const artifactLinkResp = await githubGet ( {
236
- url : "/repos/crystal-lang/crystal /actions/artifacts/:artifact_id/zip",
283
+ url : GitHubApiBase + " /actions/artifacts/:artifact_id/zip",
237
284
"artifact_id" : artifact . id ,
238
285
request : { redirect : "manual" } ,
239
286
} ) ;
0 commit comments