Skip to content

Commit

Permalink
feat: add new input repository (#283)
Browse files Browse the repository at this point in the history
  • Loading branch information
teatimeguest committed Mar 10, 2024
1 parent 1555e07 commit 1214c8b
Show file tree
Hide file tree
Showing 25 changed files with 563 additions and 236 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ All inputs are optional.
| `package-file` | String | [Glob patterns] for specifying files containing the names of TeX packages to be installed. The file format should be the same as the syntax for the `packages` input. The [`DEPENDS.txt`] format is also supported. |
| `packages` | String | Specify the names of TeX packages to install, separated by whitespaces. Schemes and collections are also acceptable. Everything after `#` will be treated as a comment. |
| `prefix` | String | <p>TeX Live installation prefix. This has the same effect as [`TEXLIVE_INSTALL_PREFIX`][install-tl-env].</p> **Default:**&ensp;<!-- dprint-ignore-start --><code>[$RUNNER_TEMP]/setup-texlive-action</code><!-- dprint-ignore-end --> |
| `repository` | URL | Specify the package repository to be used as the main repository. Currently only http/https repositories are supported. |
| `texdir` | String | TeX Live system installation directory. This has the same effect as the installer's [`-texdir`] option and takes precedence over the `prefix` input and related environment variables. |
| `tlcontrib` | Bool | <p>Set up [TLContrib] as an additional TeX package repository. This input will be ignored for older versions.</p> **Default:**&ensp;`false` |
| `update-all-packages` | Bool | <p>Update all TeX packages when cache restored. Defaults to `false`, and the action will update only `tlmgr`.</p> **Default:**&ensp;`false` |
Expand Down
11 changes: 8 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ inputs:
cache:
description: >-
Enable caching for `TEXDIR`.
default: true
default: 'true'
required: false
package-file:
description: >-
Expand All @@ -28,6 +28,11 @@ inputs:
This has the same effect as `TEXLIVE_INSTALL_PREFIX`.
Defaults to `$RUNNER_TEMP/setup-texlive-action`.
required: false
repository:
description: >-
Specify the package repository to be used as the main repository.
Currently only http/https repositories are supported.
required: false
texdir:
description: >-
TeX Live system installation directory.
Expand All @@ -39,13 +44,13 @@ inputs:
description: >-
Set up TLContrib as an additional TeX package repository.
This input will be ignored for older versions.
default: false
default: 'false'
required: false
update-all-packages:
description: >-
Update all TeX packages when cache restored.
The default is `false` and the action will update only `tlmgr`.
default: false
default: 'false'
required: false
version:
description: >-
Expand Down
8 changes: 7 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/e2e/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ tasks:
dir: '{{ .npm_config_local_prefix }}'
cmd: >-
act
--container-architecture linux/{{ ARCH }}
--container-architecture linux/{{ default ARCH .architecture }}
--workflows {{ .workflows }}
{{ .CLI_ARGS }}
clear-cache:
Expand All @@ -24,6 +24,7 @@ tasks:
historic: &run-global-workflow
<<: *act
vars:
architecture: amd64
workflows: .github/workflows/e2e-{{ .TASK }}.yml
proxy: *run-global-workflow
test:
Expand All @@ -38,3 +39,4 @@ tasks:
basedir: '{{ .TASKFILE_DIR | relPath .npm_config_local_prefix }}'
workflows: '{{ .basedir }}/workflows/{{ .TASK }}.yml'
move-to-historic: *run-local-workflow
tlpretest: *run-local-workflow
12 changes: 12 additions & 0 deletions packages/e2e/workflows/tlpretest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
on: workflow_dispatch
jobs:
tlpretest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup TeX Live
uses: ./
with:
repository: https://ftp.math.utah.edu/pub/tlpretest/
version: 2024
- run: tlmgr version
1 change: 1 addition & 0 deletions packages/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@types/mock-fs": "^4.13.4",
"mock-fs": "^5.2.0",
"nock": "^13.5.1",
"texlive-json-schemas": "^0.1.0",
"ts-dedent": "^2.2.0",
"ts-essentials": "^9.4.1",
"vitest": "^1.2.2"
Expand Down
48 changes: 39 additions & 9 deletions packages/main/src/action/config.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { readFile } from 'node:fs/promises';
import { platform } from 'node:os';
import * as posixPath from 'node:path/posix';

import { create as createGlobber } from '@actions/glob';
import type { DeepUndefinable } from 'ts-essentials';
import type { DeepUndefinable, Writable } from 'ts-essentials';

import * as env from '#/action/env';
import { Inputs } from '#/action/inputs';
import * as log from '#/log';
import { ReleaseData, Version, dependsTxt } from '#/texlive';

export interface Config
extends Omit<Inputs, 'packageFile' | 'packages' | 'version'>
extends Omit<Inputs, 'packageFile' | 'packages' | 'repository' | 'version'>
{
readonly packages: ReadonlySet<string>;
readonly repository?: Readonly<URL>;
readonly version: Version;
}

Expand All @@ -21,22 +23,50 @@ export namespace Config {
env.init();

const releases = await ReleaseData.setup();
const { packageFile, packages, version, ...inputs } = Inputs.load();
const {
packageFile,
packages,
repository,
version,
...inputs
} = Inputs.load();

const config = {
const config: Writable<Config> = {
...inputs,
version: await resolveVersion({ version }),
packages: await collectPackages({ packageFile, packages }),
};

if (!releases.isLatest(config.version)) {
if (repository !== undefined) {
if (version < '2012') {
const error = new RangeError(
'Currently `repository` input is only supported with version 2012 or later',
);
error['version'] = version;
throw error;
}
const url = new URL(repository);
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
const error = new TypeError(
'Currently only http/https repositories are supported',
);
error['repository'] = repository;
throw error;
}
if (!url.pathname.endsWith('/')) {
url.pathname = posixPath.join(url.pathname, '/');
}
config.repository = url;
}

if (config.version < releases.latest.version) {
if (config.tlcontrib) {
log.warn(`TLContrib cannot be used with an older version of TeX Live`);
log.warn('TLContrib cannot be used with an older version of TeX Live');
config.tlcontrib = false;
}
if (
!(
releases.isOnePrevious(config.version)
config.version < releases.previous.version
&& releases.newVersionReleased()
) && config.updateAllPackages
) {
Expand Down Expand Up @@ -77,7 +107,7 @@ async function collectPackages(
async function resolveVersion(
inputs: Pick<Inputs, 'version'>,
): Promise<Version> {
const { latest } = ReleaseData.use();
const { latest, next } = ReleaseData.use();
const version = inputs.version === 'latest'
? latest.version
: Version.parse(inputs.version);
Expand All @@ -89,7 +119,7 @@ async function resolveVersion(
'Versions prior to 2013 does not work on 64-bit macOS',
);
}
if (version > latest.version) {
if (version > next.version) {
throw new RangeError(`${version} is not a valid version`);
}
return version;
Expand Down
3 changes: 3 additions & 0 deletions packages/main/src/action/inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export class Inputs {
@AsPath
readonly prefix!: string;

@Input
readonly repository: string | undefined;

@Input
@AsPath
readonly texdir: string | undefined;
Expand Down
19 changes: 8 additions & 11 deletions packages/main/src/action/run/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Profile, ReleaseData, Tlmgr, tlnet } from '#/texlive';

export async function main(): Promise<void> {
const config = await Config.load();
const releases = ReleaseData.use();
const { latest, previous, newVersionReleased } = ReleaseData.use();
await using profile = new Profile(config.version, config);

using cache = CacheService.setup({
Expand All @@ -31,7 +31,7 @@ export async function main(): Promise<void> {
log.info(profile.toString());
});
await log.group('Installing TeX Live', async () => {
await install(profile);
await install({ profile, repository: config.repository });
});
}

Expand All @@ -40,18 +40,15 @@ export async function main(): Promise<void> {

if (cache.restored) {
if (
releases.isLatest(profile.version)
|| (
releases.isOnePrevious(profile.version)
&& releases.newVersionReleased()
)
profile.version >= latest.version
|| (profile.version === previous.version && newVersionReleased())
) {
await log.group(
releases.isLatest(profile.version)
profile.version >= latest.version
? 'Updating tlmgr'
: 'Checking the package repository status',
async () => {
await updateTlmgr(profile.version);
await updateTlmgr(config);
},
);
if (config.updateAllPackages) {
Expand Down Expand Up @@ -79,8 +76,8 @@ export async function main(): Promise<void> {
await log.group('TeX Live version info', async () => {
await tlmgr.version();
log.info('Package version:');
for await (const { name, version, revision } of tlmgr.list()) {
log.info(' %s: %s', name, version ?? `rev${revision}`);
for await (const { name, revision, cataloguedata } of tlmgr.list()) {
log.info(' %s: %s', name, cataloguedata?.version ?? `rev${revision}`);
}
});

Expand Down
82 changes: 60 additions & 22 deletions packages/main/src/action/run/main/install.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,79 @@
import { P, match } from 'ts-pattern';

import * as log from '#/log';
import {
type InstallTL,
InstallTLError,
Profile,
type Profile,
ReleaseData,
TlpdbError,
installTL,
acquire,
tlnet,
} from '#/texlive';

export async function install(profile: Profile): Promise<void> {
const { isLatest, isOnePrevious } = ReleaseData.use();
for (const master of [false, true]) {
const repository = isLatest(profile.version)
? await tlnet.ctan({ master })
: tlnet.historic(profile.version, { master });
log.info('Main repository: %s', repository);
export async function install(options: {
readonly profile: Profile;
readonly repository?: Readonly<URL> | undefined;
}): Promise<void> {
const { latest, previous } = ReleaseData.use();
const { version } = options.profile;

let repository = options?.repository;
const fallbackToMaster = repository === undefined
&& version > previous.version;

let installTL: InstallTL;

for (const master of fallbackToMaster ? [false, true] : [false]) {
if (repository === undefined || master) {
repository = version >= latest.version
? await tlnet.ctan({ master })
: tlnet.historic(version, { master });
}
try {
installTL ??= await acquire({ repository, version });
} catch (error) {
if (
!master
&& fallbackToMaster
&& error instanceof InstallTLError
&& match(error.code)
.with(InstallTLError.Code.FAILED_TO_DOWNLOAD, () => true)
.with(InstallTLError.Code.UNEXPECTED_VERSION, () => true)
.otherwise(() => false)
) {
log.info({ error });
continue;
}
throw error;
}
log.info('Using repository: %s', repository);
try {
await installTL({ profile, repository });
await installTL.run({
profile: options.profile,
repository: options.repository ?? repository,
});
return;
} catch (error) {
const recoverable: (InstallTLError.Code | TlpdbError.Code)[] = [
InstallTLError.Code.FAILED_TO_DOWNLOAD,
InstallTLError.Code.INCOMPATIBLE_REPOSITORY_VERSION,
InstallTLError.Code.UNEXPECTED_VERSION,
TlpdbError.Code.FAILED_TO_INITIALIZE,
];
if (
!master
&& (isLatest(profile.version) || isOnePrevious(profile.version))
&& (error instanceof TlpdbError
|| error instanceof InstallTLError)
&& recoverable.includes(error.code!)
&& fallbackToMaster
&& match(error)
.with(
P.instanceOf(TlpdbError),
({ code }) => code === TlpdbError.Code.FAILED_TO_INITIALIZE,
)
.with(
P.instanceOf(InstallTLError),
({ code }) =>
code === InstallTLError.Code.INCOMPATIBLE_REPOSITORY_VERSION,
)
.otherwise(() => false)
) {
log.info({ error });
} else {
throw error;
continue;
}
throw error;
}
}
}
Expand Down
Loading

0 comments on commit 1214c8b

Please sign in to comment.