Use github actions for CI (#2654)

This is the initial port to github actions.  Still pending are the SSL and client SSL cert tests which are currently being skipped. But perfect is the enemy of the good here, and having no CI because travis-ci keeps not working is unacceptable.
This commit is contained in:
Brian C 2021-11-17 10:02:22 -06:00 committed by GitHub
parent 947ccee346
commit 3aba3794cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 264 additions and 215 deletions

31
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: ci_db_test
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
strategy:
matrix:
node: ['8', '10', '12', '14', '16', '17']
name: Node ${{ matrix.node }}
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
cache: yarn
- run: yarn install
# TODO(bmc): get ssl tests working in ci
- run: PGTESTNOSSL=true PGUSER=postgres PGPASSWORD=postgres PGDATABASE=ci_db_test yarn test

View File

@ -88,11 +88,16 @@ if (!process.version.startsWith('v8')) {
rows.push(row)
break
}
for await (const row of stream) {
rows.push(row)
}
for await (const row of stream) {
rows.push(row)
try {
for await (const row of stream) {
rows.push(row)
}
for await (const row of stream) {
rows.push(row)
}
} catch (e) {
// swallow error - node 17 throws if stream is aborted
}
assert.strictEqual(rows.length, 1)
client.release()

View File

@ -1,15 +1,18 @@
'use strict'
var helper = require('../test-helper')
var assert = require('assert')
var ConnectionParameters = require('../../../lib/connection-parameters')
var defaults = require('../../../lib').defaults
const helper = require('../test-helper')
const assert = require('assert')
const ConnectionParameters = require('../../../lib/connection-parameters')
const defaults = require('../../../lib').defaults
const dns = require('dns')
// clear process.env
for (var key in process.env) {
delete process.env[key]
}
test('ConnectionParameters construction', function () {
const suite = new helper.Suite()
suite.test('ConnectionParameters construction', function () {
assert.ok(new ConnectionParameters(), 'with null config')
assert.ok(new ConnectionParameters({ user: 'asdf' }), 'with config object')
assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string')
@ -33,13 +36,13 @@ var compare = function (actual, expected, type) {
)
}
test('ConnectionParameters initializing from defaults', function () {
suite.test('ConnectionParameters initializing from defaults', function () {
var subject = new ConnectionParameters()
compare(subject, defaults, 'defaults')
assert.ok(subject.isDomainSocket === false)
})
test('ConnectionParameters initializing from defaults with connectionString set', function () {
suite.test('ConnectionParameters initializing from defaults with connectionString set', function () {
var config = {
user: 'brians-are-the-best',
database: 'scoobysnacks',
@ -62,7 +65,7 @@ test('ConnectionParameters initializing from defaults with connectionString set'
compare(subject, config, 'defaults-connectionString')
})
test('ConnectionParameters initializing from config', function () {
suite.test('ConnectionParameters initializing from config', function () {
var config = {
user: 'brian',
database: 'home',
@ -83,7 +86,7 @@ test('ConnectionParameters initializing from config', function () {
assert.ok(subject.isDomainSocket === false)
})
test('ConnectionParameters initializing from config and config.connectionString', function () {
suite.test('ConnectionParameters initializing from config and config.connectionString', function () {
var subject1 = new ConnectionParameters({
connectionString: 'postgres://test@host/db',
})
@ -105,31 +108,31 @@ test('ConnectionParameters initializing from config and config.connectionString'
assert.equal(subject4.ssl, true)
})
test('escape spaces if present', function () {
suite.test('escape spaces if present', function () {
var subject = new ConnectionParameters('postgres://localhost/post gres')
assert.equal(subject.database, 'post gres')
})
test('do not double escape spaces', function () {
suite.test('do not double escape spaces', function () {
var subject = new ConnectionParameters('postgres://localhost/post%20gres')
assert.equal(subject.database, 'post gres')
})
test('initializing with unix domain socket', function () {
suite.test('initializing with unix domain socket', function () {
var subject = new ConnectionParameters('/var/run/')
assert.ok(subject.isDomainSocket)
assert.equal(subject.host, '/var/run/')
assert.equal(subject.database, defaults.user)
})
test('initializing with unix domain socket and a specific database, the simple way', function () {
suite.test('initializing with unix domain socket and a specific database, the simple way', function () {
var subject = new ConnectionParameters('/var/run/ mydb')
assert.ok(subject.isDomainSocket)
assert.equal(subject.host, '/var/run/')
assert.equal(subject.database, 'mydb')
})
test('initializing with unix domain socket, the health way', function () {
suite.test('initializing with unix domain socket, the health way', function () {
var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8')
assert.ok(subject.isDomainSocket)
assert.equal(subject.host, '/some path/')
@ -137,7 +140,7 @@ test('initializing with unix domain socket, the health way', function () {
assert.equal(subject.client_encoding, 'utf8')
})
test('initializing with unix domain socket, the escaped health way', function () {
suite.test('initializing with unix domain socket, the escaped health way', function () {
var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8')
assert.ok(subject.isDomainSocket)
assert.equal(subject.host, '/some path/')
@ -145,201 +148,211 @@ test('initializing with unix domain socket, the escaped health way', function ()
assert.equal(subject.client_encoding, 'utf8')
})
test('libpq connection string building', function () {
var checkForPart = function (array, part) {
assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part)
var checkForPart = function (array, part) {
assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part)
}
const getDNSHost = async function (host) {
return new Promise((resolve, reject) => {
dns.lookup(host, (err, addresses) => {
err ? reject(err) : resolve(addresses)
})
})
}
suite.testAsync('builds simple string', async function () {
var config = {
user: 'brian',
password: 'xyz',
port: 888,
host: 'localhost',
database: 'bam',
}
test('builds simple string', function () {
var config = {
user: 'brian',
password: 'xyz',
port: 888,
host: 'localhost',
database: 'bam',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "user='brian'")
checkForPart(parts, "password='xyz'")
checkForPart(parts, "port='888'")
checkForPart(parts, "hostaddr='127.0.0.1'")
checkForPart(parts, "dbname='bam'")
})
)
})
test('builds dns string', function () {
var config = {
user: 'brian',
password: 'asdf',
port: 5432,
host: 'localhost',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "user='brian'")
checkForPart(parts, "hostaddr='127.0.0.1'")
})
)
})
test('error when dns fails', function () {
var config = {
user: 'brian',
password: 'asf',
port: 5432,
host: 'asdlfkjasldfkksfd#!$!!!!..com',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert.ok(err)
assert.isNull(constring)
})
)
})
test('connecting to unix domain socket', function () {
var config = {
user: 'brian',
password: 'asf',
port: 5432,
host: '/tmp/',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "user='brian'")
checkForPart(parts, "host='/tmp/'")
})
)
})
test('config contains quotes and backslashes', function () {
var config = {
user: 'not\\brian',
password: "bad'chars",
port: 5432,
host: '/tmp/',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "user='not\\\\brian'")
checkForPart(parts, "password='bad\\'chars'")
})
)
})
test('encoding can be specified by config', function () {
var config = {
client_encoding: 'utf-8',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "client_encoding='utf-8'")
})
)
})
test('password contains < and/or > characters', function () {
var sourceConfig = {
user: 'brian',
password: 'hello<ther>e',
port: 5432,
host: 'localhost',
database: 'postgres',
}
var connectionString =
'postgres://' +
sourceConfig.user +
':' +
sourceConfig.password +
'@' +
sourceConfig.host +
':' +
sourceConfig.port +
'/' +
sourceConfig.database
var subject = new ConnectionParameters(connectionString)
assert.equal(subject.password, sourceConfig.password)
})
test('username or password contains weird characters', function () {
var defaults = require('../../../lib/defaults')
defaults.ssl = true
var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000'
var subject = new ConnectionParameters(strang)
assert.equal(subject.user, 'my f%irst name')
assert.equal(subject.password, 'is&%awesome!')
assert.equal(subject.host, 'localhost')
assert.equal(subject.ssl, true)
})
test('url is properly encoded', function () {
var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl'
var subject = new ConnectionParameters(encoded)
assert.equal(subject.user, 'bi%na%%ry ')
assert.equal(subject.password, 's@f#')
assert.equal(subject.host, 'localhost')
assert.equal(subject.database, ' u%20rl')
})
test('ssl is set on client', function () {
var Client = require('../../../lib/client')
var defaults = require('../../../lib/defaults')
defaults.ssl = true
var c = new Client('postgres://user@password:host/database')
assert(c.ssl, 'Client should have ssl enabled via defaults')
})
test('coercing string "true" to boolean', function () {
const subject = new ConnectionParameters({ ssl: 'true' })
assert.strictEqual(subject.ssl, true)
})
test('ssl is set on client', function () {
var sourceConfig = {
user: 'brian',
password: 'hello<ther>e',
port: 5432,
host: 'localhost',
database: 'postgres',
ssl: {
sslmode: 'verify-ca',
sslca: '/path/ca.pem',
sslkey: '/path/cert.key',
sslcert: '/path/cert.crt',
sslrootcert: '/path/root.crt',
},
}
var Client = require('../../../lib/client')
var defaults = require('../../../lib/defaults')
defaults.ssl = true
var c = new ConnectionParameters(sourceConfig)
c.getLibpqConnectionString(
assert.calls(function (err, pgCString) {
assert(!err)
assert.equal(
pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1,
true,
'libpqConnectionString should contain sslrootcert'
)
})
)
var subject = new ConnectionParameters(config)
const dnsHost = await getDNSHost(config.host)
return new Promise((resolve) => {
subject.getLibpqConnectionString(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "user='brian'")
checkForPart(parts, "password='xyz'")
checkForPart(parts, "port='888'")
checkForPart(parts, `hostaddr='${dnsHost}'`)
checkForPart(parts, "dbname='bam'")
resolve()
})
})
})
suite.test('builds dns string', async function () {
var config = {
user: 'brian',
password: 'asdf',
port: 5432,
host: 'localhost',
}
var subject = new ConnectionParameters(config)
const dnsHost = await getDNSHost(config.host)
return new Promise((resolve) => {
subject.getLibpqConnectionString(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "user='brian'")
checkForPart(parts, `hostaddr='${dnsHost}'`)
resolve()
})
})
})
suite.test('error when dns fails', function () {
var config = {
user: 'brian',
password: 'asf',
port: 5432,
host: 'asdlfkjasldfkksfd#!$!!!!..com',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert.ok(err)
assert.isNull(constring)
})
)
})
suite.test('connecting to unix domain socket', function () {
var config = {
user: 'brian',
password: 'asf',
port: 5432,
host: '/tmp/',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "user='brian'")
checkForPart(parts, "host='/tmp/'")
})
)
})
suite.test('config contains quotes and backslashes', function () {
var config = {
user: 'not\\brian',
password: "bad'chars",
port: 5432,
host: '/tmp/',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "user='not\\\\brian'")
checkForPart(parts, "password='bad\\'chars'")
})
)
})
suite.test('encoding can be specified by config', function () {
var config = {
client_encoding: 'utf-8',
}
var subject = new ConnectionParameters(config)
subject.getLibpqConnectionString(
assert.calls(function (err, constring) {
assert(!err)
var parts = constring.split(' ')
checkForPart(parts, "client_encoding='utf-8'")
})
)
})
suite.test('password contains < and/or > characters', function () {
var sourceConfig = {
user: 'brian',
password: 'hello<ther>e',
port: 5432,
host: 'localhost',
database: 'postgres',
}
var connectionString =
'postgres://' +
sourceConfig.user +
':' +
sourceConfig.password +
'@' +
sourceConfig.host +
':' +
sourceConfig.port +
'/' +
sourceConfig.database
var subject = new ConnectionParameters(connectionString)
assert.equal(subject.password, sourceConfig.password)
})
suite.test('username or password contains weird characters', function () {
var defaults = require('../../../lib/defaults')
defaults.ssl = true
var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000'
var subject = new ConnectionParameters(strang)
assert.equal(subject.user, 'my f%irst name')
assert.equal(subject.password, 'is&%awesome!')
assert.equal(subject.host, 'localhost')
assert.equal(subject.ssl, true)
})
suite.test('url is properly encoded', function () {
var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl'
var subject = new ConnectionParameters(encoded)
assert.equal(subject.user, 'bi%na%%ry ')
assert.equal(subject.password, 's@f#')
assert.equal(subject.host, 'localhost')
assert.equal(subject.database, ' u%20rl')
})
suite.test('ssl is set on client', function () {
var Client = require('../../../lib/client')
var defaults = require('../../../lib/defaults')
defaults.ssl = true
var c = new Client('postgres://user@password:host/database')
assert(c.ssl, 'Client should have ssl enabled via defaults')
})
suite.test('coercing string "true" to boolean', function () {
const subject = new ConnectionParameters({ ssl: 'true' })
assert.strictEqual(subject.ssl, true)
})
suite.test('ssl is set on client', function () {
var sourceConfig = {
user: 'brian',
password: 'hello<ther>e',
port: 5432,
host: 'localhost',
database: 'postgres',
ssl: {
sslmode: 'verify-ca',
sslca: '/path/ca.pem',
sslkey: '/path/cert.key',
sslcert: '/path/cert.crt',
sslrootcert: '/path/root.crt',
},
}
var Client = require('../../../lib/client')
var defaults = require('../../../lib/defaults')
defaults.ssl = true
var c = new ConnectionParameters(sourceConfig)
c.getLibpqConnectionString(
assert.calls(function (err, pgCString) {
assert(!err)
assert.equal(
pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1,
true,
'libpqConnectionString should contain sslrootcert'
)
})
)
})