Skip to content
This repository was archived by the owner on Oct 10, 2022. It is now read-only.

Commit fe7aa14

Browse files
biilmannbcomnes
authored andcommitted
Deploy functions with zip-it-and-ship-it
1 parent f242511 commit fe7aa14

File tree

3 files changed

+31
-71
lines changed

3 files changed

+31
-71
lines changed

src/deploy/hash-fns.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ async function hashFns(dir, opts) {
3535
const fnShaMap = {} //hash: [fileObj, fileObj, fileObj]
3636
const manifestCollector = manifestCollectorCtor(functions, fnShaMap, opts)
3737

38-
// TODO: Zip up functions, hash then send.
39-
// This is totally wrong right now.
40-
// See https://github.com/netlify/open-api/blob/master/go/porcelain/deploy.go#L544
41-
4238
await pump(fileStream, fnStat, fnFilter, hasher, manifestCollector)
4339

4440
return { functions, fnShaMap }

src/deploy/hasher-segments.js

Lines changed: 31 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
const objFilterCtor = require('through2-filter').objCtor
22
const objWriter = require('flush-write-stream').obj
3-
const { isExe, normalizePath } = require('./util')
3+
const { normalizePath } = require('./util')
44
const transform = require('parallel-transform')
55
const hasha = require('hasha')
66
const path = require('path')
77
const fs = require('fs')
88
const map = require('through2-map').obj
9-
const pump = require('pump')
10-
const archiver = require('archiver')
9+
const zipIt = require('zip-it-and-ship-it')
1110

1211
// a parallel transform stream segment ctor that hashes fileObj's created by folder-walker
1312
exports.hasherCtor = ({ concurrentHash, hashAlgorithm = 'sha1' }) => {
13+
const hashaOpts = { algorithm: hashAlgorithm }
1414
if (!concurrentHash) throw new Error('Missing required opts')
1515
return transform(concurrentHash, { objectMode: true }, (fileObj, cb) => {
1616
hasha
17-
.fromFile(fileObj.filepath, { algorithm: hashAlgorithm })
17+
.fromFile(fileObj.filepath, hashaOpts)
1818
// insert hash and asset type to file obj
1919
.then(hash => cb(null, Object.assign({}, fileObj, { hash })))
2020
.catch(err => cb(err))
@@ -59,64 +59,42 @@ exports.fileFilterCtor = objFilterCtor(fileObj => {
5959

6060
exports.fnFilterCtor = objFilterCtor(fileObj => {
6161
// filter additional files out of our fn pipeline
62-
return fileObj.type === 'file' && !!fileObj.runtime
62+
return fileObj && fileObj.type === 'file' && !!fileObj.runtime
6363
})
6464

65-
// Zip a file into a temporary directory
66-
function zipFunction(item, tmpDir, cb) {
67-
const zipPath = path.join(tmpDir, item.normalizedPath + '.zip')
68-
const output = fs.createWriteStream(zipPath)
69-
const archive = archiver('zip')
70-
71-
archive.file(item.filepath, { name: item.basename })
72-
archive.finalize()
73-
74-
pump(archive, output, err => {
75-
if (err) return cb(err)
76-
77-
item.filepath = zipPath
78-
cb(null, item)
79-
})
80-
}
81-
8265
// parallel stream ctor similar to folder-walker but specialized for netlify functions
8366
// Stream in names of files that may be functions, and this will stat the file and return a fileObj
8467
exports.fnStatCtor = ({ root, concurrentStat, tmpDir }) => {
8568
if (!concurrentStat || !root || !tmpDir) throw new Error('Missing required opts')
8669
return transform(concurrentStat, { objectMode: true }, (name, cb) => {
87-
const filepath = path.join(root, name)
70+
const filepath = path.resolve(path.join(root, name))
8871
fs.stat(filepath, (err, stat) => {
8972
if (err) return cb(err)
90-
91-
const item = {
92-
root,
93-
filepath,
94-
stat,
95-
relname: path.relative(root, filepath),
96-
basename: path.basename(name),
97-
extname: path.extname(name),
98-
type: stat.isFile() ? 'file' : stat.isDirectory() ? 'directory' : null,
99-
assetType: 'function',
100-
normalizedPath: path.basename(name, path.extname(name))
101-
}
102-
103-
if (['.zip'].some(ext => item.extname === ext)) {
104-
item.runtime = 'js'
105-
return cb(null, item)
106-
}
107-
108-
if (['.js'].some(ext => item.extname === ext)) {
109-
item.runtime = 'js'
110-
111-
return zipFunction(item, tmpDir, cb)
112-
}
113-
114-
if (isExe(item.stat)) {
115-
item.runtime = 'go'
116-
return zipFunction(item, tmpDir, cb)
117-
}
118-
119-
return cb(null, item)
73+
zipIt
74+
.zipFunction(filepath, tmpDir)
75+
.then(functionZip => {
76+
if (functionZip === null) {
77+
return cb(null, null)
78+
}
79+
80+
const item = {
81+
root,
82+
filepath: functionZip.path,
83+
stat,
84+
relname: path.relative(root, filepath),
85+
basename: path.basename(name),
86+
extname: path.extname(name),
87+
type: 'file',
88+
assetType: 'function',
89+
normalizedPath: path.basename(name, path.extname(name)),
90+
runtime: functionZip.runtime
91+
}
92+
93+
cb(null, item)
94+
})
95+
.catch(err => {
96+
cb(err, null)
97+
})
12098
})
12199
})
122100
}

src/deploy/util.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,18 +115,4 @@ function getUploadList(required, shaMap) {
115115
return flatten(required.map(sha => shaMap[sha]))
116116
}
117117

118-
// given a Stat object, return if its executable or not
119-
// https://github.com/jokeyrhyme/is-executable.js without the io
120-
exports.isExe = stat => {
121-
const { mode, gid, uid } = stat
122-
if (process.platform === 'win32') {
123-
return true
124-
}
125-
126-
const isGroup = gid ? process.getgid && gid === process.getgid() : true
127-
const isUser = uid ? process.getuid && uid === process.getuid() : true
128-
129-
return Boolean(mode & 0o0001 || (mode & 0o0010 && isGroup) || (mode & 0o0100 && isUser))
130-
}
131-
132118
exports.retry = async (fn, errHandler, opts) => {}

0 commit comments

Comments
 (0)