Skip to content

Commit 3507539

Browse files
authored
feat(build): include manual file in packages MONGOSH-1017 (#1144)
1 parent d48113d commit 3507539

File tree

14 files changed

+113
-7
lines changed

14 files changed

+113
-7
lines changed

config/build.conf.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ const os = require('os');
88
*/
99
const ROOT = path.join(__dirname, '..');
1010

11+
/**
12+
* The tmp folder location.
13+
*/
14+
const TMP_DIR = path.join(ROOT, 'tmp');
15+
1116
/**
1217
* The mongosh package.
1318
*/
@@ -44,7 +49,7 @@ const EXECUTABLE_PATH = path.join(OUTPUT_DIR, process.platform === 'win32' ? 'mo
4449
* We use the name mongocryptd-mongosh to avoid conflicts with users
4550
* potentially installing the 'proper' mongocryptd package.
4651
*/
47-
const MONGOCRYPTD_PATH = path.resolve(__dirname, '..', 'tmp', 'mongocryptd-mongosh' + (process.platform === 'win32' ? '.exe' : ''));
52+
const MONGOCRYPTD_PATH = path.resolve(TMP_DIR, 'mongocryptd-mongosh' + (process.platform === 'win32' ? '.exe' : ''));
4853

4954
/**
5055
* Build info JSON data file.
@@ -66,6 +71,11 @@ const REVISION = process.env.GITHUB_COMMIT ?? process.env.REVISION;
6671
*/
6772
const COPYRIGHT = `${new Date().getYear() + 1900} MongoDB, Inc.`;
6873

74+
/**
75+
* The manual page file name
76+
*/
77+
const MANPAGE_NAME = 'mongosh.1.gz'
78+
6979
/**
7080
* Export the configuration for the build.
7181
*/
@@ -141,6 +151,10 @@ module.exports = {
141151
packagedFilePath: 'THIRD_PARTY_NOTICES'
142152
}
143153
],
154+
manpage: {
155+
sourceFilePath: path.resolve(TMP_DIR, 'manpage', MANPAGE_NAME),
156+
packagedFilePath: MANPAGE_NAME,
157+
},
144158
metadata: {
145159
name: 'mongosh',
146160
rpmName: 'mongodb-mongosh',
@@ -159,5 +173,10 @@ module.exports = {
159173
debTemplateDir: path.resolve(__dirname, '..', 'packaging', 'deb-template'),
160174
rpmTemplateDir: path.resolve(__dirname, '..', 'packaging', 'rpm-template'),
161175
msiTemplateDir: path.resolve(__dirname, '..', 'packaging', 'msi-template')
162-
}
176+
},
177+
manpage: {
178+
sourceUrl: 'https://docs.mongodb.com/mongodb-shell/manpages.tar.gz',
179+
downloadPath: path.resolve(TMP_DIR, 'manpage'),
180+
fileName: MANPAGE_NAME,
181+
},
163182
};

packages/build/src/config/config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import type { PackageInformation } from '../packaging/package';
22
import { BuildVariant } from './build-variant';
33

4+
interface ManPageConfig {
5+
sourceUrl: string;
6+
downloadPath: string;
7+
fileName: string;
8+
}
9+
410
/**
511
* Defines the configuration interface for the build system.
612
*/
@@ -42,4 +48,5 @@ export interface Config {
4248
mongocryptdPath: string;
4349
packageInformation?: PackageInformation;
4450
artifactUrlFile?: string;
51+
manpage?: ManPageConfig;
4552
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import nock from 'nock';
2+
import { join } from 'path';
3+
import { promises as fs } from 'fs';
4+
import { downloadManpage } from './download-manpage';
5+
6+
describe('packaging download manpage', () => {
7+
it('downloads manpage', async() => {
8+
nock('http://example.com')
9+
.get('/')
10+
.replyWithFile(
11+
200,
12+
join(__dirname, '..', '..', 'test', 'fixtures', 'manpages.tar.gz')
13+
);
14+
15+
const destination = join(__dirname, '..', '..', 'tmp', 'manpage');
16+
const name = 'manpages.gz';
17+
await downloadManpage('http://example.com', destination, name);
18+
await fs.access(join(destination, name));
19+
});
20+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import fetch from 'node-fetch';
2+
import tar from 'tar';
3+
import { createReadStream, createWriteStream, promises as fs } from 'fs';
4+
import { promisify } from 'util';
5+
import { join } from 'path';
6+
import { pipeline } from 'stream';
7+
import { createGzip } from 'zlib';
8+
9+
export async function downloadManpage(url: string, destination: string, name: string) {
10+
await fs.mkdir(destination, { recursive: true });
11+
const response = await fetch(url);
12+
await promisify(pipeline)(
13+
response.body,
14+
tar.x({ cwd: destination })
15+
);
16+
await promisify(pipeline)(
17+
createReadStream(join(destination, 'mongosh.1')),
18+
createGzip(),
19+
createWriteStream(join(destination, name))
20+
);
21+
console.info(`Saved manpage: ${join(destination, name)}`);
22+
}

packages/build/src/packaging/package/debian.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ describe('tarball debian', () => {
3030
expect(stdout).to.match(/^-rw-r.-r--.+\/usr\/share\/doc\/foobar\/LICENSE_foo$/m);
3131
expect(stdout).to.match(/^-rw-r.-r--.+\/usr\/share\/doc\/foobar\/README$/m);
3232
expect(stdout).to.match(/^-rw-r.-r--.+\/usr\/share\/doc\/foobar\/copyright$/m);
33+
expect(stdout).to.match(/^-rw-r.-r--.+\/usr\/share\/man\/man1\/mongosh.1.gz$/m);
3334
}
3435
{
3536
const { stdout } = await execFile('dpkg', ['-I', tarball.path]);

packages/build/src/packaging/package/debian.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ export async function createDebianPackage(
3535
for (const { sourceFilePath, packagedFilePath } of docFiles) {
3636
await fs.copyFile(sourceFilePath, path.join(docdir, packagedFilePath), COPYFILE_FICLONE);
3737
}
38+
39+
if (pkg.manpage) {
40+
// Put manpage file in /usr/share/man/man1/.
41+
const manualDir = path.join(dir, pkg.metadata.debName, 'usr', 'share', 'man', 'man1');
42+
await fs.mkdir(manualDir, { recursive: true });
43+
await fs.copyFile(pkg.manpage.sourceFilePath, path.join(manualDir, pkg.manpage.packagedFilePath), COPYFILE_FICLONE);
44+
}
45+
3846
// Debian packages should contain a 'copyright' file.
3947
// https://www.debian.org/doc/debian-policy/ch-archive.html#s-pkgcopyright
4048
await fs.writeFile(path.join(docdir, 'copyright'), await generateDebianCopyright(pkg));

packages/build/src/packaging/package/helpers.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ export async function createCompressedArchiveContents(archiveRootName: string, p
3434
await fs.mkdir(archiveRoot, { recursive: true });
3535
const docFiles = [
3636
...pkg.otherDocFilePaths,
37-
...pkg.binaries.map(({ license }) => license)
37+
...pkg.binaries.map(({ license }) => license),
3838
];
39+
if (pkg.manpage) {
40+
docFiles.push(pkg.manpage);
41+
}
42+
3943
for (const { sourceFilePath, packagedFilePath } of docFiles) {
4044
await fs.copyFile(sourceFilePath, path.join(archiveRoot, packagedFilePath), COPYFILE_FICLONE);
4145
}

packages/build/src/packaging/package/package-information.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ interface LicenseInformation extends DocumentationFile {
99
rpmIdentifier: string;
1010
}
1111

12+
type ManPage = DocumentationFile;
13+
1214
// This is filled in by the build config file.
1315
export interface PackageInformation {
1416
binaries: {
@@ -17,6 +19,7 @@ export interface PackageInformation {
1719
license: LicenseInformation;
1820
}[];
1921
otherDocFilePaths: DocumentationFile[];
22+
manpage?: ManPage;
2023
metadata: {
2124
name: string;
2225
debName: string;

packages/build/src/packaging/package/redhat.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ describe('tarball redhat', () => {
3838
expect(stdout).to.match(/^\/usr\/share\/doc\/foobar-1.0.0\/README$/m);
3939
expect(stdout).to.match(/^\/usr\/share\/licenses\/foobar-1.0.0\/LICENSE_bar$/m);
4040
expect(stdout).to.match(/^\/usr\/share\/licenses\/foobar-1.0.0\/LICENSE_foo$/m);
41+
expect(stdout).to.match(/^\/usr\/share\/man\/man1\/mongosh.1.gz$/m);
4142
});
4243

4344
it('determines and copies created RPM', async() => {

packages/build/src/packaging/package/redhat.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,17 @@ export async function createRedhatPackage(
3535
const filelistRpm = [
3636
...pkg.binaries.map(({ sourceFilePath, category }) => `%{_${category}dir}/${path.basename(sourceFilePath)}`),
3737
...pkg.binaries.map(({ license }) => `%license ${license.packagedFilePath}`),
38-
...pkg.otherDocFilePaths.map(({ packagedFilePath }) => `%doc ${packagedFilePath}`)
39-
].join('\n');
38+
...pkg.otherDocFilePaths.map(({ packagedFilePath }) => `%doc ${packagedFilePath}`),
39+
];
40+
if (pkg.manpage) {
41+
filelistRpm.push(`%doc ${pkg.manpage.packagedFilePath}`);
42+
}
4043
const version = sanitizeVersion(pkg.metadata.version, 'rpm');
4144
const dir = await generateDirFromTemplate(templateDir, {
4245
...pkg.metadata,
4346
licenseRpm,
4447
installscriptRpm,
45-
filelistRpm,
48+
filelistRpm: filelistRpm.join('\n'),
4649
version
4750
});
4851
// Copy all files that we want to ship into the BUILD directory.
@@ -56,6 +59,10 @@ export async function createRedhatPackage(
5659
await fs.copyFile(sourceFilePath, path.join(dir, 'BUILD', packagedFilePath), COPYFILE_FICLONE);
5760
}
5861

62+
if (pkg.manpage) {
63+
await fs.copyFile(pkg.manpage.sourceFilePath, path.join(dir, 'BUILD', pkg.manpage.packagedFilePath), COPYFILE_FICLONE);
64+
}
65+
5966
// Create the package.
6067
await execFile('rpmbuild', [
6168
'-bb', path.join(dir, 'SPECS', `${pkg.metadata.rpmName}.spec`),

0 commit comments

Comments
 (0)