# runtime/entrypoints/deployment.entrypoint.ts

> 128 lines of code and 17 definitions.

Tree: Bane's Lab Deploy
Language: typescript
Layer: runtime
Canonical: https://banes-lab.com/anatomy/deploy#file-deploy-runtime-entrypoints-deployment-entrypoint-ts
Source text: https://banes-lab.com/source/deploy/runtime/entrypoints/deployment.entrypoint.ts.txt

Listed in [runtime/entrypoints](https://banes-lab.com/api/source/deploy/runtime/entrypoints.md), before [runtime/entrypoints/nginx.entrypoint.ts](https://banes-lab.com/source/deploy/runtime/entrypoints/nginx.entrypoint.ts.md).

## Definitions

- `ship` (lexical_declaration, line 86)
- `summarize` (lexical_declaration, line 41)
- `release` (lexical_declaration, line 51)
- `run` (lexical_declaration, line 108)
- `backup` (lexical_declaration, line 57)
- `managed` (lexical_declaration, line 58)
- `stats` (lexical_declaration, line 61)
- `outcome` (lexical_declaration, line 68)
- `before` (lexical_declaration, line 95)
- `reported` (lexical_declaration, line 99)
- `after` (lexical_declaration, line 100)
- `secrets` (lexical_declaration, line 109)
- `journal` (lexical_declaration, line 110)
- `shell` (lexical_declaration, line 111)
- `startedAt` (lexical_declaration, line 112)
- `failure` (lexical_declaration, line 116)
- `span` (lexical_declaration, line 118)

## Contained in

- [runtime/entrypoints](https://banes-lab.com/anatomy/deploy/folder-deploy-runtime-entrypoints.md)

## Uses

- [core/converters/failure.converter.ts](https://banes-lab.com/source/deploy/core/converters/failure.converter.ts.md)
- [core/converters/text.converter.ts](https://banes-lab.com/source/deploy/core/converters/text.converter.ts.md)
- [core/reporters/deployment.reporter.ts](https://banes-lab.com/source/deploy/core/reporters/deployment.reporter.ts.md)
- [core/steps/backup.step.ts](https://banes-lab.com/source/deploy/core/steps/backup.step.ts.md)
- [core/steps/certificate.step.ts](https://banes-lab.com/source/deploy/core/steps/certificate.step.ts.md)
- [core/steps/nginx.step.ts](https://banes-lab.com/source/deploy/core/steps/nginx.step.ts.md)
- [core/steps/probe.step.ts](https://banes-lab.com/source/deploy/core/steps/probe.step.ts.md)
- [core/steps/recovery.step.ts](https://banes-lab.com/source/deploy/core/steps/recovery.step.ts.md)
- [core/steps/remote.step.ts](https://banes-lab.com/source/deploy/core/steps/remote.step.ts.md)
- [core/steps/search.step.ts](https://banes-lab.com/source/deploy/core/steps/search.step.ts.md)
- [core/steps/setup.step.ts](https://banes-lab.com/source/deploy/core/steps/setup.step.ts.md)
- [core/steps/site.step.ts](https://banes-lab.com/source/deploy/core/steps/site.step.ts.md)

## Linked from

- [core/converters](https://banes-lab.com/anatomy/deploy/folder-deploy-core-converters.md)
- [core/reporters](https://banes-lab.com/anatomy/deploy/folder-deploy-core-reporters.md)
- [core/steps](https://banes-lab.com/anatomy/deploy/folder-deploy-core-steps.md)
- [runtime/entrypoints](https://banes-lab.com/anatomy/deploy/folder-deploy-runtime-entrypoints.md)

## Source

```typescript
import {
    CONNECTED,
    CONNECTING,
    DEPLOY_DONE,
    DEPLOY_FAILED,
    DEPLOY_START,
    FATAL,
    ROLLBACK_FAILED,
    SECONDS_SUFFIX,
    SITEMAP_UNBUILT,
    SUMMARY_BACKUP,
    SUMMARY_DURATION,
    SUMMARY_FILES,
    SUMMARY_SIZE,
    SUMMARY_TITLE,
    UPLOAD_OF,
} from "#configuration/strings/deployment.strings";
import type { Journal, ManagedBackup, Outcome, Secrets, Shell, UploadStats } from "#types/deployment.types";
import { archiveSite, pruneArchives, restoreSite } from "#core/steps/backup.step";
import { buildSite, validateSite } from "#core/steps/site.step";
import { formatBytes, formatDuration } from "#core/converters/text.converter";
import { pullManaged, restoreManaged } from "#core/steps/recovery.step";
import { PAGE_SITEMAP_ROUTE } from "@banes-lab/build-scripts/configuration/constants/site.constants.ts";
import { SITE_URL } from "@banes-lab/web/core/assets/link.assets.ts";
import { createJournal } from "#core/reporters/journal.reporter";
import { createShell } from "#core/adapters/shell.adapter";
import { fetchIndex } from "#core/adapters/package.adapter";
import { loadSecrets } from "#core/loaders/environment.loader";
import { messageOf } from "#core/converters/failure.converter";
import { pingSearch } from "#core/steps/search.step";
import { prepareServer } from "#core/steps/setup.step";
import { probeCertificate } from "#core/steps/certificate.step";
import { probeSite } from "#core/steps/probe.step";
import { pruneRemoteRoot } from "#core/steps/remote.step";
import { readLive } from "#core/adapters/search.adapter";
import { readOrNull } from "@banes-lab/build-scripts/core/loaders/build.loader.ts";
import { reportDeployment } from "#core/reporters/deployment.reporter";
import { uploadSite } from "#core/steps/release.step";
import { verifyNginx } from "#core/steps/nginx.step";

const summarize = function summarize(journal: Journal, stats: UploadStats, outcome: Outcome): void {
    journal.log(SUMMARY_TITLE);
    journal.log(SUMMARY_FILES + String(stats.uploadedCount) + UPLOAD_OF + String(stats.totalFileCount));
    journal.log(SUMMARY_SIZE + formatBytes(stats.totalBytes));
    journal.log(SUMMARY_DURATION + formatDuration(outcome.span.finishedAt - outcome.span.startedAt) + SECONDS_SUFFIX);
    journal.log(SUMMARY_BACKUP + outcome.backup);
    journal.log(DEPLOY_DONE);
    journal.log(SITE_URL);
};

const release = async function release(
    shell: Shell,
    journal: Journal,
    secrets: Secrets,
    startedAt: number,
): Promise<boolean> {
    const backup = await archiveSite(shell, journal);
    let managed: readonly ManagedBackup[] = [];
    try {
        pruneArchives(journal);
        const stats = await uploadSite(shell, journal);
        await pruneRemoteRoot(shell, journal);
        managed = await pullManaged(shell, journal);
        await prepareServer(shell, journal, fetchIndex);
        await verifyNginx(shell, journal);
        await probeSite(journal, SITE_URL, shell);
        await probeCertificate(journal, SITE_URL);
        const outcome: Outcome = { backup, failure: "", span: { finishedAt: Date.now(), startedAt }, stats };
        const reported = await reportDeployment(journal, secrets.deployWebhook, outcome);
        summarize(journal, stats, outcome);
        return reported;
    } catch (error: unknown) {
        journal.error(DEPLOY_FAILED + messageOf(error));
        try {
            if (managed.length > 0) {
                await restoreManaged(shell, journal, managed);
            }
            await restoreSite(shell, journal, backup);
        } catch (rollbackError: unknown) {
            journal.error(ROLLBACK_FAILED + messageOf(rollbackError));
        }
        throw error;
    }
};

const ship = async function ship(
    shell: Shell,
    journal: Journal,
    secrets: Secrets,
    startedAt: number,
): Promise<boolean> {
    journal.log(DEPLOY_START);
    await buildSite(journal);
    await validateSite(journal);
    const before = await readLive(SITE_URL + PAGE_SITEMAP_ROUTE);
    journal.log(CONNECTING);
    await shell.connect();
    journal.mark(CONNECTED);
    const reported = await release(shell, journal, secrets, startedAt);
    const after = readOrNull(PAGE_SITEMAP_ROUTE.slice(1));
    if (after === null) {
        throw new Error(SITEMAP_UNBUILT + PAGE_SITEMAP_ROUTE);
    }
    await pingSearch(journal, SITE_URL, secrets.searchKey, { after, before });
    return reported;
};

const run = async function run(): Promise<number> {
    const secrets = loadSecrets();
    const journal = createJournal();
    const shell = createShell(secrets);
    const startedAt = Date.now();
    try {
        return (await ship(shell, journal, secrets, startedAt)) ? 0 : 1;
    } catch (error: unknown) {
        const failure = messageOf(error);
        journal.error(DEPLOY_FAILED + failure);
        const span = { finishedAt: Date.now(), startedAt };
        await reportDeployment(journal, secrets.deployWebhook, { backup: "", failure, span, stats: null });
        return 1;
    } finally {
        shell.dispose();
    }
};

run()
    .then((status) => {
        process.exitCode = status;
    })
    .catch((error: unknown) => {
        console.error(FATAL + messageOf(error));
        process.exitCode = 1;
    });
```
