Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Package standalone binaries via @vercel/pkg #343

Open
wants to merge 40 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c828996
add package-standalone npm script to run vercel/pkg on the minified b…
trxcllnt Dec 23, 2022
9829ed9
update yarn.lock
trxcllnt Dec 23, 2022
dea73bc
copy scripts/updateUID.Dockerfile into standalone packages
trxcllnt Jan 3, 2023
e32c3b5
update tests to optionally execute the standalone binary instead of t…
trxcllnt Jan 3, 2023
7b16b80
update dev-containers.yml workflow to build, upload, and test the sta…
trxcllnt Jan 3, 2023
fb00be8
setup QEMU
trxcllnt Jan 3, 2023
4f7a744
fix typos
trxcllnt Jan 3, 2023
7716f15
run standalone binary tests on windows
trxcllnt Jan 3, 2023
4ab41ea
separate scripts for building each os/arch combo
trxcllnt Jan 4, 2023
873be77
update yarn.lock
trxcllnt Jan 4, 2023
6a4a539
update actions to build macos binaries, download artifact for testing…
trxcllnt Jan 4, 2023
7f6d4ae
build the pkgs on separate OS's
trxcllnt Jan 4, 2023
97c6f70
update registryCompatibilityOCI.test.ts
trxcllnt Jan 4, 2023
817a9b4
add package-standalone npm script to run vercel/pkg on the minified b…
trxcllnt Dec 23, 2022
8d4beea
update yarn.lock
trxcllnt Dec 23, 2022
dc37f6d
copy scripts/updateUID.Dockerfile into standalone packages
trxcllnt Jan 3, 2023
fc745df
update tests to optionally execute the standalone binary instead of t…
trxcllnt Jan 3, 2023
3210199
update dev-containers.yml workflow to build, upload, and test the sta…
trxcllnt Jan 3, 2023
3ec97a3
setup QEMU
trxcllnt Jan 3, 2023
a57398d
fix typos
trxcllnt Jan 3, 2023
9d51488
run standalone binary tests on windows
trxcllnt Jan 3, 2023
6177f68
separate scripts for building each os/arch combo
trxcllnt Jan 4, 2023
fd39253
update yarn.lock
trxcllnt Jan 4, 2023
1b5907d
update registryCompatibilityOCI.test.ts
trxcllnt Jan 4, 2023
1a8bc5a
Merge branch 'main' of github.com:devcontainers/cli into fea/pkg
trxcllnt Jan 21, 2023
6f4afce
Merge branch 'fea/pkg' into fea/pkg-workflows
trxcllnt Jan 21, 2023
2fb68ae
silence buffer ctor deprecation warnings
trxcllnt Jan 21, 2023
b146bb6
publish github releases with artifacts
trxcllnt Jan 22, 2023
9ff701f
build on older OS versions
trxcllnt Jan 24, 2023
6a1ecfc
cache bust on os change
trxcllnt Jan 24, 2023
6131899
Merge branch 'main' into fea/pkg
joshspicer Feb 7, 2023
a62cd9f
Merge branch 'fea/pkg' into fea/pkg-workflows
trxcllnt Feb 7, 2023
9ae26cb
ensure ts-node doesn't attempt to transpile node-pty tests
trxcllnt Feb 7, 2023
5c70bfa
Merge branch 'fea/pkg' into fea/pkg-workflows
trxcllnt Feb 7, 2023
132285f
Merge branch 'main' of github.com:devcontainers/cli into fea/pkg
trxcllnt Jun 6, 2023
fea1d81
add comment that COMPILE_FOR_PKG is inlined
trxcllnt Jun 6, 2023
f9e26da
add dist/node_modules to assets
trxcllnt Jun 6, 2023
e77ae41
Merge branch 'main' of github.com:devcontainers/cli into fea/pkg
trxcllnt Sep 26, 2023
e266aeb
rename dev-containers.yml
trxcllnt Sep 26, 2023
ab02fbb
restore original dev-containers.yml
trxcllnt Sep 26, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions .github/workflows/dev-containers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,40 @@ jobs:
run: yarn type-check
- name: Lint
run: yarn lint
- name: Set up QEMU
trxcllnt marked this conversation as resolved.
Show resolved Hide resolved
uses: docker/setup-qemu-action@v2
- name: Package
run: yarn package
- name: TGZ name
run: yarn package && yarn package-standalone
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few warnings in CI:

> Warning Cannot resolve 't'
472
  /home/runner/work/cli/cli/dist/spec-node/devContainersSpecCLI.js
473
  Dynamic require may fail at run time, because the requested file
474
  is unknown at compilation time and not included into executable.
475
  Use a string literal as an argument for 'require', or leave it
476
  as is and specify the resolved file name in 'scripts' option.
477
> Warning Cannot resolve 't.extends'
478
  /home/runner/work/cli/cli/dist/spec-node/devContainersSpecCLI.js
479
  Dynamic require may fail at run time, because the requested file
480
  is unknown at compilation time and not included into executable.
481
  Use a string literal as an argument for 'require', or leave it
482
  as is and specify the resolved file name in 'scripts' option.
483
> Warning Cannot resolve 't'
484
  /home/runner/work/cli/cli/dist/spec-node/devContainersSpecCLI.js
485
  Dynamic require may fail at run time, because the requested file
486
  is unknown at compilation time and not included into executable.
487
  Use a string literal as an argument for 'require', or leave it
488
  as is and specify the resolved file name in 'scripts' option.
489
prebuild-install WARN install No prebuilt binaries found (target=v16.16.0 runtime=node arch=x64 libc= platform=linux)
490
prebuild-install WARN install No prebuilt binaries found (target=v16.16.0 runtime=node arch=arm64 libc= platform=linux)
491
prebuild-install WARN install No prebuilt binaries found (target=v16.16.0 runtime=node arch=x64 libc= platform=win32)
492
prebuild-install WARN install No prebuilt binaries found (target=v16.16.0 runtime=node arch=arm64 libc= platform=win32)

Have you looked into the 'cannot resolve' warnings?

The prebuild-install warnings seem to indicate that the node-pty module is not available for the target.
From my testing of the build artifacts:

  • Windows ARM binary doesn't show any output (just seems to immediately exit).
  • Windows x64 binary shows help, but build fails with 'pty.node is not a valid Win32 application'.
  • Linux ARM binary shows help, but build fails with 'pty.node: cannot open shared object file: No such file or directory'.
  • Linux x64 binary works.

Copy link
Contributor Author

@trxcllnt trxcllnt Feb 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I recall, the cannot resolve t warnings are the dynamic require/import calls in yargs (t is the mangled name).

You're noticing some of the reasons I split things across this PR and #385 🙂.

#385 compiles the binaries on each target OS, because I realized @vercel/pkg wasn't cross-compiling the native modules from linux (their docs seem ambiguous at best). I thought they may have included logic to re-run node-gyp to recompile a native module (kinda similar to electron's packager).

I wasn't sure how they'd do that without the target's compilers, but I'll admit I'm ignorant of the current state of cross-compiling from linux to windows/macos.

- name: Version and tag
run: |
VERSION=$(jq -r '.version' < package.json)
echo "TGZ=devcontainers-cli-${VERSION}.tgz" | tee -a $GITHUB_ENV
echo "TGZ_UPLOAD=devcontainers-cli-${VERSION}-${GITHUB_SHA:0:8}.tgz" | tee -a $GITHUB_ENV
echo "VER=${VERSION}" | tee -a $GITHUB_ENV
echo "TAG=${VERSION}-${GITHUB_SHA:0:8}" | tee -a $GITHUB_ENV
- name: Store TGZ
uses: actions/upload-artifact@v2
with:
name: ${{ env.TGZ_UPLOAD }}
path: ${{ env.TGZ }}
name: devcontainers-cli-${{ env.TAG }}.tgz
path: devcontainers-cli-${{ env.VER }}.tgz
- name: Store devcontainer-linux-x64
uses: actions/upload-artifact@v2
with:
name: devcontainer-linux-x64-${{ env.TAG }}
path: dist/devcontainer-linux-x64
- name: Store devcontainer-linux-arm64
uses: actions/upload-artifact@v2
with:
name: devcontainer-linux-arm64-${{ env.TAG }}
path: dist/devcontainer-linux-arm64
- name: Store devcontainer-win-x64.exe
uses: actions/upload-artifact@v2
with:
name: devcontainer-win-x64-${{ env.TAG }}.exe
path: dist/devcontainer-win-x64.exe
- name: Store devcontainer-win-arm64.exe
uses: actions/upload-artifact@v2
with:
name: devcontainer-win-arm64-${{ env.TAG }}.exe
path: dist/devcontainer-win-arm64.exe
tests-matrix:
name: Tests Matrix
runs-on: ubuntu-latest
Expand Down Expand Up @@ -73,9 +95,13 @@ jobs:
- name: Type-Check
run: yarn type-check
- name: Package
run: yarn package
run: yarn package && yarn package-standalone-linux-x64
- name: Run Tests
run: yarn test-matrix --forbid-only ${{ matrix.mocha-args }}
- name: Run Tests on standalone binary
trxcllnt marked this conversation as resolved.
Show resolved Hide resolved
env:
TEST_STANDALONE_PKG: 1
run: yarn test-matrix --forbid-only ${{ matrix.mocha-args }}
tests:
name: Tests
needs: tests-matrix
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/test-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ jobs:
- name: Type-Check
run: yarn type-check
- name: Package
run: yarn package
run: yarn package && yarn package-standalone-win-x64
- name: Run Tests
run: yarn test-matrix --forbid-only ${{ matrix.mocha-args-windows }}
run: yarn test-matrix --forbid-only ${{ matrix.mocha-args-windows }}
- name: Run Tests on standalone binary
trxcllnt marked this conversation as resolved.
Show resolved Hide resolved
env:
TEST_STANDALONE_PKG: 1
run: yarn test-matrix --forbid-only ${{ matrix.mocha-args-windows }}
6 changes: 5 additions & 1 deletion esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const fs = require('fs');
const path = require('path');
const uri = require('vscode-uri');

const compileForPkg = process.argv.indexOf('--compile-for-pkg') !== -1;
const minify = process.argv.indexOf('--production') !== -1;
const watch = process.argv.indexOf('--watch') !== -1;

Expand Down Expand Up @@ -58,7 +59,10 @@ const watch = process.argv.indexOf('--watch') !== -1;
watch,
platform: 'node',
target: 'node14.14.0',
external: ['vscode-dev-containers'],
external: ['vscode-dev-containers'].concat(compileForPkg ? ['node-pty'] : []),
define: {
'process.env.COMPILE_FOR_PKG': `${compileForPkg === true}`
},
mainFields: ['module', 'main'],
outdir: 'dist',
plugins: [plugin],
Expand Down
28 changes: 26 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@
"scripts": {
"compile": "npm-run-all clean-dist definitions compile-dev",
"watch": "npm-run-all clean-dist definitions compile-watch",
"package-standalone": "npm-run-all clean-dist definitions compile-prod-for-pkg pkg-pack",
"package-standalone-linux-x64": "npm-run-all clean-dist definitions compile-prod-for-pkg pkg-pack-linux-x64",
"package-standalone-linux-arm64": "npm-run-all clean-dist definitions compile-prod-for-pkg pkg-pack-linux-arm64",
"package-standalone-win-x64": "npm-run-all clean-dist definitions compile-prod-for-pkg pkg-pack-win-x64",
"package-standalone-win-arm64": "npm-run-all clean-dist definitions compile-prod-for-pkg pkg-pack-win-arm64",
"package": "npm-run-all clean-dist definitions compile-prod store-packagejson patch-packagejson npm-pack restore-packagejson",
"store-packagejson": "copyfiles package.json build-tmp/",
"patch-packagejson": "node build/patch-packagejson.js",
"restore-packagejson": "copyfiles --up 1 build-tmp/package.json .",
"type-check": "npm-run-all clean-built tsc-b",
"type-check-watch": "npm-run-all clean-built tsc-b-w",
"compile-prod": "node esbuild.js --production",
"compile-prod-for-pkg": "node esbuild.js --production --compile-for-pkg",
"compile-dev": "node esbuild.js",
"compile-watch": "node esbuild.js --watch",
"tsc-b": "tsc -b",
Expand All @@ -37,14 +43,30 @@
"definitions-clean": "rimraf dist/node_modules/vscode-dev-containers",
"definitions-copy": "copyfiles --all \"node_modules/vscode-dev-containers/**/*\" dist",
"npm-pack": "npm pack",
"pkg-pack": "cross-env PKG_CACHE_PATH=node_modules/.pkg-cache pkg -c package.json -o dist/devcontainer devcontainer.js",
"pkg-pack-linux-x64": "cross-env PKG_CACHE_PATH=node_modules/.pkg-cache pkg -c package.json -o dist/devcontainer-linux-x64 -t linux-x64 devcontainer.js",
"pkg-pack-linux-arm64": "cross-env PKG_CACHE_PATH=node_modules/.pkg-cache pkg -c package.json -o dist/devcontainer-linux-arm64 -t linux-arm64 devcontainer.js",
"pkg-pack-win-x64": "cross-env PKG_CACHE_PATH=node_modules/.pkg-cache pkg -c package.json -o dist/devcontainer-win-x64 -t win-x64 devcontainer.js",
"pkg-pack-win-arm64": "cross-env PKG_CACHE_PATH=node_modules/.pkg-cache pkg -c package.json -o dist/devcontainer-win-arm64 -t win-arm64 devcontainer.js",
"clean": "npm-run-all clean-dist clean-built",
"clean-dist": "rimraf dist",
"clean-built": "rimraf built",
"test": "env TS_NODE_PROJECT=src/test/tsconfig.json mocha -r ts-node/register --exit src/test/*.test.ts",
"test-matrix": "env TS_NODE_PROJECT=src/test/tsconfig.json mocha -r ts-node/register --exit",
"test": "env TS_NODE_PROJECT=src/test/tsconfig.json mocha -r ts-node/register --exit --exclude '**/node_modules/**/*.ts' 'src/test/**/*.test.ts'",
"test-matrix": "env TS_NODE_PROJECT=src/test/tsconfig.json mocha -r ts-node/register --exit --exclude '**/node_modules/**/*.ts'",
"test-container-features": "env TS_NODE_PROJECT=src/test/tsconfig.json mocha -r ts-node/register --exit src/test/container-features/*.test.ts",
"test-container-templates": "env TS_NODE_PROJECT=src/test/tsconfig.json mocha -r ts-node/register --exit src/test/container-templates/*.test.ts"
},
"pkg": {
"assets": [
"scripts/updateUID.Dockerfile"
trxcllnt marked this conversation as resolved.
Show resolved Hide resolved
],
"targets": [
"linux-x64",
"linux-arm64",
"win-x64",
"win-arm64"
]
},
"files": [
"CHANGELOG.md",
"LICENSE.txt",
Expand Down Expand Up @@ -75,6 +97,7 @@
"@typescript-eslint/parser": "^5.45.1",
"chai": "^4.3.7",
"copyfiles": "^2.4.1",
"cross-env": "^7.0.3",
"esbuild": "^0.16.1",
"eslint": "^8.29.0",
"event-stream": "^4.0.1",
Expand All @@ -83,6 +106,7 @@
"mocha": "^10.1.0",
"npm-run-all": "^4.1.5",
"p-all": "^4.0.0",
"pkg": "^5.8.0",
"rimraf": "^3.0.2",
"ts-node": "^10.9.1",
"typescript": "^4.9.3",
Expand Down
4 changes: 3 additions & 1 deletion src/spec-common/commonUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,9 @@ export function plainExec(defaultCwd: string | undefined): ExecFunction {
}

export async function plainPtyExec(defaultCwd: string | undefined, loadNativeModule: <T>(moduleName: string) => Promise<T | undefined>): Promise<PtyExecFunction> {
const pty = await loadNativeModule<typeof ptyType>('node-pty');
const pty = !!process.env.COMPILE_FOR_PKG
trxcllnt marked this conversation as resolved.
Show resolved Hide resolved
? (require('node-pty') as typeof ptyType)
: (await loadNativeModule<typeof ptyType>('node-pty'));
if (!pty) {
throw new Error('Missing node-pty');
}
Expand Down
6 changes: 4 additions & 2 deletions src/spec-shutdown/dockerUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,9 @@ export function dockerExecFunction(params: DockerCLIParameters | PartialExecPara
}

export async function dockerPtyExecFunction(params: PartialPtyExecParameters | DockerResolverParameters, containerName: string, user: string | undefined, loadNativeModule: <T>(moduleName: string) => Promise<T | undefined>): Promise<PtyExecFunction> {
const pty = await loadNativeModule<typeof ptyType>('node-pty');
const pty = !!process.env.COMPILE_FOR_PKG
trxcllnt marked this conversation as resolved.
Show resolved Hide resolved
? (require('node-pty') as typeof ptyType)
: (await loadNativeModule<typeof ptyType>('node-pty'));
if (!pty) {
throw new Error('Missing node-pty');
}
Expand Down Expand Up @@ -429,4 +431,4 @@ export function toDockerImageName(name: string) {
.toLowerCase()
.replace(/[^a-z0-9\._-]+/g, '')
.replace(/(\.[\._-]|_[\.-]|__[\._-]|-+[\._])[\._-]*/g, (_, a) => a.substr(0, a.length - 1));
}
}
15 changes: 5 additions & 10 deletions src/test/cli.build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,18 @@

import * as fs from 'fs';
import * as assert from 'assert';
import * as path from 'path';
import * as os from 'os';
import { buildKitOptions, shellExec } from './testUtils';
import { buildKitOptions, shellExec, setupCLI } from './testUtils';

const pkg = require('../../package.json');

describe('Dev Containers CLI', function () {
this.timeout('120s');

const tmp = path.relative(process.cwd(), path.join(__dirname, 'tmp'));
const cli = `npx --prefix ${tmp} devcontainer`;
const { cli, installCLI, uninstallCLI } = setupCLI(pkg.version);

before('Install', async () => {
await shellExec(`rm -rf ${tmp}/node_modules`);
await shellExec(`mkdir -p ${tmp}`);
await shellExec(`npm --prefix ${tmp} install devcontainers-cli-${pkg.version}.tgz`);
});
before('Install', installCLI);
after('Install', uninstallCLI);

describe('Command build', () => {

Expand Down Expand Up @@ -238,4 +233,4 @@ describe('Dev Containers CLI', function () {
await shellExec(`docker rm -f ${containerId}`);
});
});
});
});
25 changes: 8 additions & 17 deletions src/test/cli.exec.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import * as assert from 'assert';
import * as path from 'path';
import { BuildKitOption, commandMarkerTests, devContainerDown, devContainerStop, devContainerUp, pathExists, shellExec } from './testUtils';
import { BuildKitOption, commandMarkerTests, devContainerDown, devContainerStop, devContainerUp, pathExists, shellExec, setupCLI } from './testUtils';

const pkg = require('../../package.json');

Expand All @@ -14,14 +13,10 @@ export function describeTests1({ text, options }: BuildKitOption) {
describe('Dev Containers CLI', function () {
this.timeout('240s');

const tmp = path.relative(process.cwd(), path.join(__dirname, 'tmp'));
const cli = `npx --prefix ${tmp} devcontainer`;
const { cli, installCLI, uninstallCLI } = setupCLI(pkg.version);

before('Install', async () => {
await shellExec(`rm -rf ${tmp}/node_modules`);
await shellExec(`mkdir -p ${tmp}`);
await shellExec(`npm --prefix ${tmp} install devcontainers-cli-${pkg.version}.tgz`);
});
before('Install', installCLI);
after('Install', uninstallCLI);

describe('Command exec', () => {

Expand Down Expand Up @@ -150,14 +145,10 @@ export function describeTests2({ text, options }: BuildKitOption) {
describe('Dev Containers CLI', function () {
this.timeout('300s');

const tmp = path.relative(process.cwd(), path.join(__dirname, 'tmp'));
const cli = `npx --prefix ${tmp} devcontainer`;
const { cli, installCLI, uninstallCLI } = setupCLI(pkg.version);

before('Install', async () => {
await shellExec(`rm -rf ${tmp}/node_modules`);
await shellExec(`mkdir -p ${tmp}`);
await shellExec(`npm --prefix ${tmp} install devcontainers-cli-${pkg.version}.tgz`);
});
before('Install', installCLI);
after('Install', uninstallCLI);

describe('Command exec', () => {

Expand Down Expand Up @@ -346,7 +337,7 @@ export function describeTests2({ text, options }: BuildKitOption) {
assert.match(res.stderr, /howdy, node/);
});
});

it('should fail with "not found" error when config is not found', async () => {
let success = false;
try {
Expand Down
15 changes: 5 additions & 10 deletions src/test/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,17 @@
*--------------------------------------------------------------------------------------------*/

import * as assert from 'assert';
import * as path from 'path';
import { devContainerDown, devContainerUp, shellExec } from './testUtils';
import { devContainerDown, devContainerUp, shellExec, setupCLI } from './testUtils';

const pkg = require('../../package.json');

describe('Dev Containers CLI', function () {
this.timeout('120s');

const tmp = path.relative(process.cwd(), path.join(__dirname, 'tmp'));
const cli = `npx --prefix ${tmp} devcontainer`;
const { cli, installCLI, uninstallCLI } = setupCLI(pkg.version);

before('Install', async () => {
await shellExec(`rm -rf ${tmp}/node_modules`);
await shellExec(`mkdir -p ${tmp}`);
await shellExec(`npm --prefix ${tmp} install devcontainers-cli-${pkg.version}.tgz`);
});
before('Install', installCLI);
after('Install', uninstallCLI);

it('Global --help', async () => {
const res = await shellExec(`${cli} --help`);
Expand Down Expand Up @@ -103,4 +98,4 @@ describe('Dev Containers CLI', function () {
}
});
});
});
});
14 changes: 5 additions & 9 deletions src/test/cli.up.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,17 @@ import * as assert from 'assert';
import * as path from 'path';
import * as fs from 'fs';
import * as os from 'os';
import { devContainerDown, devContainerUp, shellExec, UpResult, pathExists } from './testUtils';
import { devContainerDown, devContainerUp, shellExec, UpResult, pathExists, setupCLI } from './testUtils';

const pkg = require('../../package.json');

describe('Dev Containers CLI', function () {
this.timeout('120s');

const tmp = path.relative(process.cwd(), path.join(__dirname, 'tmp'));
const cli = `npx --prefix ${tmp} devcontainer`;
const { cli, installCLI, uninstallCLI } = setupCLI(pkg.version);

before('Install', async () => {
await shellExec(`rm -rf ${tmp}/node_modules`);
await shellExec(`mkdir -p ${tmp}`);
await shellExec(`npm --prefix ${tmp} install devcontainers-cli-${pkg.version}.tgz`);
});
before('Install', installCLI);
after('Install', uninstallCLI);

describe('Command up', () => {
it('should execute successfully with valid config', async () => {
Expand Down Expand Up @@ -179,4 +175,4 @@ describe('Dev Containers CLI', function () {
await shellExec(`docker rm -f ${containerId}`);
});
});
});
});
Loading