11/* eslint no-console: 0 */
22/* eslint max-len: 0 */
33import path from 'path' ;
4- import GitHubApi from 'github' ;
4+
55import program from 'commander' ;
66import minimatch from 'minimatch' ;
77import pkg from '../package.json' ;
8+ import * as LinkHeader from 'http-link-header' ;
9+ const URL = require ( 'url-parse' ) ;
10+ import * as mime from 'mime-types' ;
11+
12+ import Octokit from '@octokit/rest' ;
13+ const octokit = new Octokit ( ) ;
814
915program
1016 . version ( pkg . version )
@@ -32,115 +38,20 @@ program.parse(process.argv);
3238
3339const [ command , ...args ] = program . args ;
3440
35- const github = new GitHubApi ( {
36- version : '3.0.0' ,
37- timeout : 5000 ,
38- headers : {
39- 'user-agent' : 'GitHub-Release-App'
40- }
41- } ) ;
42-
43- github . authenticate ( {
41+ octokit . authenticate ( {
4442 type : 'oauth' ,
4543 token : program . token || process . env . GITHUB_TOKEN
4644} ) ;
4745
48- const getReleaseByTag = ( options ) => {
49- return new Promise ( async ( resolve , reject ) => {
50- try {
51- let page = 1 ;
52- let lastPage = 1 ;
53- let foundRelease = false ;
46+ function next ( response ) {
47+ if ( ! response . headers || ! response . headers . link ) return false ;
5448
55- do {
56- const releases = await getReleases ( {
57- owner : options . owner ,
58- repo : options . repo ,
59- page : page ,
60- per_page : 30
61- } ) ;
62-
63- const searchedReleases = releases . filter ( r => ( r . tag_name === options . tag ) || ( r . name === options . tag ) ) ;
64- if ( searchedReleases . length ) {
65- resolve ( releases [ 0 ] ) ;
66- foundRelease = true ;
67- break ;
68- }
69-
70- const pagination = ( releases . meta . link || '' ) . split ( ',' )
71- . reduce ( ( acc , link ) => {
72- const r = link . match ( / \? p a g e = ( \d ) + .* r e l = " ( \w + ) " / ) ;
73- if ( r && r [ 1 ] && r [ 2 ] ) {
74- const key = r [ 2 ] ;
75- const value = Number ( r [ 1 ] ) || 0 ;
76- acc [ key ] = value ;
77- }
78- return acc ;
79- } , { } ) ;
80-
81- if ( pagination . last > 0 ) {
82- lastPage = pagination . last ;
83- }
84-
85- ++ page ;
86- } while ( page <= lastPage ) ;
87-
88- if ( ! foundRelease ) {
89- reject ( 'Cannot find release' ) ;
90- }
91- } catch ( err ) {
92- reject ( err ) ;
93- }
94- } ) ;
95- } ;
96-
97- const getReleases = ( options ) => {
98- return new Promise ( ( resolve , reject ) => {
99- github . repos . getReleases ( options , ( err , res ) => {
100- err ? reject ( err ) : resolve ( res ) ;
101- } ) ;
102- } ) ;
103- } ;
104-
105- const createRelease = ( options ) => {
106- return new Promise ( ( resolve , reject ) => {
107- github . repos . createRelease ( options , ( err , res ) => {
108- err ? reject ( err ) : resolve ( res ) ;
109- } ) ;
110- } ) ;
111- } ;
112-
113- const editRelease = ( options ) => {
114- return new Promise ( ( resolve , reject ) => {
115- github . repos . editRelease ( options , ( err , res ) => {
116- err ? reject ( err ) : resolve ( res ) ;
117- } ) ;
118- } ) ;
119- } ;
120-
121- const getAssets = ( options ) => {
122- return new Promise ( ( resolve , reject ) => {
123- github . repos . getAssets ( options , ( err , res ) => {
124- err ? reject ( err ) : resolve ( res ) ;
125- } ) ;
126- } ) ;
127- } ;
128-
129- const deleteAsset = ( options ) => {
130- return new Promise ( ( resolve , reject ) => {
131- github . repos . deleteAsset ( options , ( err , res ) => {
132- err ? reject ( err ) : resolve ( res ) ;
133- } ) ;
134- } ) ;
135- } ;
136-
137- const uploadAsset = ( options ) => {
138- return new Promise ( ( resolve , reject ) => {
139- github . repos . uploadAsset ( options , ( err , res ) => {
140- err ? reject ( err ) : resolve ( res ) ;
141- } ) ;
142- } ) ;
143- } ;
49+ let link = LinkHeader . parse ( response . headers . link ) . rel ( 'next' ) ;
50+ if ( ! link ) return false ;
51+ link = URL ( link [ 0 ] . uri , null , true ) . query
52+ if ( ! link ) return false ;
53+ return parseInt ( link . page ) ;
54+ }
14455
14556const fn = {
14657 'upload' : async ( ) => {
@@ -150,7 +61,7 @@ const fn = {
15061
15162 try {
15263 console . log ( '> releases#getReleaseByTag' ) ;
153- release = await getReleaseByTag ( {
64+ release = await octokit . repos . getReleaseByTag ( {
15465 owner : owner ,
15566 repo : repo ,
15667 tag : tag
@@ -162,47 +73,43 @@ const fn = {
16273 try {
16374 if ( ! release ) {
16475 console . log ( '> releases#createRelease' ) ;
165- release = await createRelease ( {
166- owner : owner ,
167- repo : repo ,
76+ result = await octokit . repos . createRelease ( {
77+ owner,
78+ repo,
16879 tag_name : tag ,
16980 name : name || tag ,
17081 body : body || '' ,
17182 draft : ! ! draft ,
17283 prerelease : ! ! prerelease
173- } ) ;
84+ } )
17485 } else {
175- console . log ( '> releases#editRelease ' ) ;
176- let releaseOptions = {
177- owner : owner ,
178- repo : repo ,
179- id : release . id ,
86+ console . log ( '> releases#updateRelease ' ) ;
87+ release = await octokit . repos . updateRelease ( {
88+ owner,
89+ repo,
90+ release_id : release . id ,
18091 tag_name : tag ,
18192 name : name || tag ,
182- body : ( body === undefined )
183- ? release . body || ''
184- : body || '' ,
185- draft : ( draft === undefined )
186- ? ! ! release . draft
187- : false ,
188- prerelease : ( prerelease === undefined )
189- ? ! ! release . prerelease
190- : false
191- } ;
192- release = await editRelease ( releaseOptions ) ;
93+ body : ( body === undefined ) ? release . body || '' : body || '' ,
94+ draft : ( draft === undefined ) ? ! ! release . draft : false ,
95+ prerelease : ( prerelease === undefined ) ? ! ! release . prerelease : false ,
96+ } )
19397 }
19498
19599 if ( files . length > 0 ) {
196- console . log ( '> releases#uploadAsset ' ) ;
100+ console . log ( '> releases#uploadReleaseAsset ' ) ;
197101 for ( let i = 0 ; i < files . length ; ++ i ) {
198102 const file = files [ i ] ;
199103 console . log ( '#%d name="%s" filePath="%s"' , i + 1 , path . basename ( file ) , file ) ;
200- await uploadAsset ( {
201- owner : owner ,
202- repo : repo ,
203- id : release . id ,
204- filePath : file ,
205- name : path . basename ( file )
104+
105+ await octokit . repos . uploadReleaseAsset ( {
106+ url : release . data . upload_url ,
107+ file : fs . createReadStream ( file ) ,
108+ headers : {
109+ 'content-type' : mime . lookup ( 'file' ) || 'application/octet-stream' ,
110+ 'content-length' : fs . statSync ( file ) . size ,
111+ } ,
112+ name : path . basename ( asset ) ,
206113 } ) ;
207114 }
208115 }
@@ -217,7 +124,7 @@ const fn = {
217124
218125 try {
219126 console . log ( '> releases#getReleaseByTag' ) ;
220- release = await getReleaseByTag ( {
127+ release = await octokit . repos . getReleaseByTag ( {
221128 owner : owner ,
222129 repo : repo ,
223130 tag : tag
@@ -228,19 +135,24 @@ const fn = {
228135 }
229136
230137 try {
231- console . log ( '> releases#getAssets' ) ;
232- const assets = await getAssets ( {
233- owner : owner ,
234- repo : repo ,
235- id : release . id
236- } ) ;
138+ console . log ( '> releases#listAssetsForRelease' ) ;
139+
140+ let assets = [ ] ;
141+ let _assets = null ;
142+ let page = 1 ;
143+ do {
144+ let _assets = await octokit . repos . listAssetsForRelease ( { owner, repo, release_id, per_page, page} )
145+ assets = assets . concat ( _assets . data )
146+ page = next ( _assets )
147+ } while ( page )
148+
237149 const deleteAssets = assets . filter ( asset => {
238150 return patterns . some ( pattern => minimatch ( asset . name , pattern ) ) ;
239151 } ) ;
240152 console . log ( 'assets=%d, deleteAssets=%d' , assets . length , deleteAssets . length ) ;
241153
242154 if ( deleteAssets . length > 0 ) {
243- console . log ( '> releases#deleteAsset ' ) ;
155+ console . log ( '> releases#deleteReleaseAsset ' ) ;
244156 for ( let i = 0 ; i < deleteAssets . length ; ++ i ) {
245157 const asset = deleteAssets [ i ] ;
246158 console . log ( '#%d' , i + 1 , {
@@ -253,17 +165,36 @@ const fn = {
253165 created_at : asset . created_at ,
254166 updated_at : asset . updated_at
255167 } ) ;
256- await deleteAsset ( {
257- owner : owner ,
258- repo : repo ,
259- id : asset . id
260- } ) ;
168+ await octokit . repos . deleteReleaseAsset ( { owner, repo, asset_id : asset . id } )
261169 }
262170 }
263171 } catch ( err ) {
264172 console . error ( err ) ;
265173 }
266- }
174+ } ,
175+ 'list' : async ( ) => {
176+ let releases = null ;
177+ let page = 1 ;
178+ do {
179+ releases = await octokit . repos . listReleases ( { owner : program . owner , repo : program . repo , page } ) ;
180+ for ( const release of releases . data ) {
181+ console . log ( `${ release . name } (${ release . tag_name } )` ) ;
182+ }
183+
184+ page = next ( releases )
185+ } while ( page )
186+ } ,
267187} [ command ] ;
268188
269- typeof fn === 'function' && fn ( ) ;
189+ async function main ( ) {
190+ try {
191+ typeof fn === 'function' && await fn ( ) ;
192+ } catch ( err ) {
193+ // message has token in the response
194+ const message = err . message . replace ( / h t t p s ? : [ ^ \s ] * / g, ( match ) => match . replace ( / \? .* / , '' ) )
195+ console . log ( message ) ;
196+ process . exit ( 1 ) ;
197+ }
198+ }
199+
200+ main ( )
0 commit comments