Skip to content

Commit

Permalink
Merge pull request #1100 from stevedlawrence:reproducible-vsix
Browse files Browse the repository at this point in the history
Allow for reproducible .vsix packages
  • Loading branch information
benibenj authored Dec 11, 2024
2 parents 0a22db7 + c367404 commit 033d602
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 12 deletions.
18 changes: 13 additions & 5 deletions src/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ export class ManifestProcessor extends BaseProcessor {
if (!minEngineVersion) {
throw new Error('Failed to get minVersion of engines.vscode')
}

if (target) {
if (engineSemver.version !== 'latest' && !semver.satisfies(minEngineVersion, '>=1.61', { includePrerelease: true })) {
throw new Error(
Expand Down Expand Up @@ -1804,12 +1804,20 @@ function writeVsix(files: IFile[], packagePath: string): Promise<void> {
() =>
new Promise((c, e) => {
const zip = new yazl.ZipFile();
const zipOptions: Partial<yazl.Options> = {};

// reproducible zip files
const sde = process.env.SOURCE_DATE_EPOCH;
if (sde) {
const epoch = parseInt(sde);
zipOptions.mtime = new Date(epoch * 1000);
files = files.sort((a, b) => a.path.localeCompare(b.path))
}

files.forEach(f =>
isInMemoryFile(f)
? zip.addBuffer(typeof f.contents === 'string' ? Buffer.from(f.contents, 'utf8') : f.contents, f.path, {
mode: f.mode,
})
: zip.addFile(f.localPath, f.path, { mode: f.mode })
? zip.addBuffer(typeof f.contents === 'string' ? Buffer.from(f.contents, 'utf8') : f.contents, f.path, { ...zipOptions, mode: f.mode })
: zip.addFile(f.localPath, f.path, { ...zipOptions, mode: f.mode })
);
zip.end();

Expand Down
53 changes: 46 additions & 7 deletions src/test/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
versionBump,
VSIX,
LicenseProcessor,
printAndValidatePackagedFiles,
printAndValidatePackagedFiles, pack
} from '../package';
import { ManifestPackage } from '../manifest';
import * as path from 'path';
Expand Down Expand Up @@ -2286,13 +2286,13 @@ describe('ManifestProcessor', () => {
});

it('should not throw error for engine version with x (e.g. 1.95.x)', async () => {
const root = fixture('uuid');
const manifest = JSON.parse(await fs.promises.readFile(path.join(root, 'package.json'), 'utf8'));
manifest.engines.vscode = '1.95.x'; // Non-strict semver, but acceptable
const root = fixture('uuid');
const manifest = JSON.parse(await fs.promises.readFile(path.join(root, 'package.json'), 'utf8'));
manifest.engines.vscode = '1.95.x'; // Non-strict semver, but acceptable

assert.doesNotThrow(() => new ManifestProcessor(manifest, { target: 'web' }));
assert.doesNotThrow(() => new ManifestProcessor(manifest, { preRelease: true }));
});
assert.doesNotThrow(() => new ManifestProcessor(manifest, { target: 'web' }));
assert.doesNotThrow(() => new ManifestProcessor(manifest, { preRelease: true }));
});
});

describe('MarkdownProcessor', () => {
Expand Down Expand Up @@ -3196,3 +3196,42 @@ describe('version', function () {
assert.strictEqual(newManifest.version, '1.0.0');
});
});

describe('writeVsix', function () {
this.timeout(60_000);

it('should be reproducible', async () => {
const exampleProject = fixture('manifestFiles');
const fixtureDir = fixture('');

const testDir = tmp.dirSync({ unsafeCleanup: true, tmpdir: fixtureDir });
const cwd = testDir.name

try {
fs.cpSync(exampleProject, cwd, { recursive: true });

const createVsix = async (vsixPath: string, epoch: number) => {
process.env["SOURCE_DATE_EPOCH"] = `${epoch}`;
await pack({ cwd, packagePath: vsixPath });
}

const vsix1 = testDir.name + '/vsix1.vsix';
const vsix2 = testDir.name + '/vsix2.vsix';
const vsix3 = testDir.name + '/vsix3.vsix';

await createVsix(vsix1, 1000000000);
await createVsix(vsix2, 1000000000);
await createVsix(vsix3, 1000000002);

const vsix1bytes = fs.readFileSync(vsix1);
const vsix2bytes = fs.readFileSync(vsix2);
const vsix3bytes = fs.readFileSync(vsix3);

assert.deepStrictEqual(vsix1bytes, vsix2bytes);
assert.notDeepStrictEqual(vsix1bytes, vsix3bytes);

} finally {
testDir.removeCallback();
}
});
});

0 comments on commit 033d602

Please sign in to comment.