Skip to content

Commit

Permalink
feat: Adds unity3d datasource
Browse files Browse the repository at this point in the history
  • Loading branch information
ViMaSter committed Feb 20, 2024
1 parent 085d70b commit 29d3cd7
Show file tree
Hide file tree
Showing 7 changed files with 41,776 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/modules/datasource/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import { SbtPluginDatasource } from './sbt-plugin';
import { TerraformModuleDatasource } from './terraform-module';
import { TerraformProviderDatasource } from './terraform-provider';
import type { DatasourceApi } from './types';
import { Unity3dDatasource } from './unity3d';

const api = new Map<string, DatasourceApi>();
export default api;
Expand Down Expand Up @@ -126,3 +127,4 @@ api.set(SbtPackageDatasource.id, new SbtPackageDatasource());
api.set(SbtPluginDatasource.id, new SbtPluginDatasource());
api.set(TerraformModuleDatasource.id, new TerraformModuleDatasource());
api.set(TerraformProviderDatasource.id, new TerraformProviderDatasource());
api.set(Unity3dDatasource.id, new Unity3dDatasource());
34,026 changes: 34,026 additions & 0 deletions lib/modules/datasource/unity3d/__fixtures__/beta.xml

Large diffs are not rendered by default.

3,865 changes: 3,865 additions & 0 deletions lib/modules/datasource/unity3d/__fixtures__/lts.xml

Large diffs are not rendered by default.

3,694 changes: 3,694 additions & 0 deletions lib/modules/datasource/unity3d/__fixtures__/stable.xml

Large diffs are not rendered by default.

115 changes: 115 additions & 0 deletions lib/modules/datasource/unity3d/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { getPkgReleases } from '..';
import { Fixtures } from '../../../../test/fixtures';
import * as httpMock from '../../../../test/http-mock';
import { Unity3dDatasource } from '.';

const mockRSSFeeds = (streams: { [keys: string]: string }) => {
Object.entries(streams).map(([stream, url]) => {
const content = Fixtures.get(stream + '.xml');

const uri = new URL(url);

httpMock.scope(uri.origin).get(uri.pathname).reply(200, content);
});
};

describe('modules/datasource/unity3d/index', () => {
it('returns stable and lts releases by default', async () => {
const qualifyingStreams = { ...Unity3dDatasource.streams };
delete qualifyingStreams.beta;
mockRSSFeeds(qualifyingStreams);
const responses = (
await getPkgReleases({
datasource: Unity3dDatasource.id,
packageName: 'm_EditorVersion',
registryUrls: Object.values(qualifyingStreams),
})
)?.releases.map((release) => release.version);

// check that only letter f is present (final releases)
expect(responses!.every((version) => /[fp]/.test(version))).toBe(true);
// check that no version contains the letter b (beta release)
expect(responses!.every((version) => !/b/.test(version))).toBe(true);
});

it('returns hash if requested', async () => {
mockRSSFeeds({ stable: Unity3dDatasource.streams.stable });
const responsesWithoutHash = (await getPkgReleases({
datasource: Unity3dDatasource.id,
packageName: 'm_EditorVersionWithRevision',
registryUrls: [Unity3dDatasource.streams.stable],
}))!.releases.map((release) => release.version);

expect(responsesWithoutHash.length).toBeGreaterThan(0);
expect(
responsesWithoutHash.every((version) => /\(.*\)/.test(version)),
).toBe(true);
});

it('returns no hash if not requested', async () => {
mockRSSFeeds({ stable: Unity3dDatasource.streams.stable });
const responsesWithoutHash = (
await getPkgReleases({
datasource: Unity3dDatasource.id,
packageName: 'm_EditorVersion',
registryUrls: [Unity3dDatasource.streams.stable],
})
)?.releases.map((release) => release.version);

expect(responsesWithoutHash!.length).toBeGreaterThan(0);
expect(
responsesWithoutHash!.every((version) => !/\(.*\)/.test(version)),
).toBe(true);
});

it('returns different versions for each stream', async () => {
mockRSSFeeds(Unity3dDatasource.streams);
const responses: { [keys: string]: string[] } = Object.fromEntries(
await Promise.all(
Object.keys(Unity3dDatasource.streams).map(async (stream) => [
stream,
(
await getPkgReleases({
datasource: Unity3dDatasource.id,
packageName: 'm_EditorVersion',
registryUrls: [Unity3dDatasource.streams[stream]],
})
)?.releases.map((release) => release.version),
]),
),
);

// none of the items in responses.beta are in responses.stable or responses.lts
expect(
responses.beta.every(
(betaVersion) =>
!responses.stable.includes(betaVersion) &&
!responses.lts.includes(betaVersion),
),
).toBe(true);
// some items in responses.stable are in responses.lts
expect(
responses.stable.some((stableVersion) =>
responses.lts.includes(stableVersion),
),
).toBe(true);
// not all items in responses.stable are in responses.lts
expect(
responses.stable.every((stableVersion) =>
responses.lts.includes(stableVersion),
),
).toBe(false);
});

it('returns only lts and stable by default', async () => {
const qualifyingStreams = { ...Unity3dDatasource.streams };
delete qualifyingStreams.beta;
mockRSSFeeds(qualifyingStreams);
const responses = (await getPkgReleases({
datasource: Unity3dDatasource.id,
packageName: 'm_EditorVersionWithRevision',
}))!.releases.map((release) => release.version);

expect(responses.every((version) => /[fp]/.test(version))).toBe(true);
});
});
73 changes: 73 additions & 0 deletions lib/modules/datasource/unity3d/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { XmlDocument } from 'xmldoc';
import { cache } from '../../../util/cache/package/decorator';
import * as Unity3dVersioning from '../../versioning/unity3d';
import { Datasource } from '../datasource';
import type { GetReleasesConfig, Release, ReleaseResult } from '../types';

export class Unity3dDatasource extends Datasource {
static readonly streams: { [key: string]: string } = {
lts: 'https://unity.com/releases/editor/lts-releases.xml',
stable: 'https://unity.com/releases/editor/releases.xml',
beta: 'https://unity.com/releases/editor/beta/latest.xml',
};

static readonly id = 'unity3d';

override readonly defaultRegistryUrls = [
Unity3dDatasource.streams.stable,
Unity3dDatasource.streams.lts,
];

override readonly defaultVersioning = Unity3dVersioning.id;

override readonly registryStrategy = 'merge';

constructor() {
super(Unity3dDatasource.id);
}

getByStream = async (
registryUrl: string | undefined,
withHash: boolean,
): Promise<ReleaseResult | null> => {
const response = await this.http.get(registryUrl!);
const document = new XmlDocument(response.body);
const releases = document
.childNamed('channel')!
.childrenNamed('item')
.map((itemNode) => {
const versionWithHash = `${itemNode.childNamed('title')?.val} (${itemNode.childNamed('guid')?.val})`;
const versionWithoutHash = itemNode.childNamed('title')?.val;
const release: Release = {
version: withHash ? versionWithHash : versionWithoutHash!,
releaseTimestamp: itemNode.childNamed('pubDate')?.val,
changelogUrl: itemNode.childNamed('link')?.val,
isStable: registryUrl !== Unity3dDatasource.streams.beta,
registryUrl,
};
return release;
})
.filter((release): release is Release => !!release);

return {
releases,
homepage: 'https://unity.com/',
};
};

@cache({
namespace: `datasource-${Unity3dDatasource.id}`,
key: ({ registryUrl, packageName }: GetReleasesConfig) =>
`${registryUrl}:${packageName}`,
ttlMinutes: 24 * 60,
})
async getReleases({
packageName,
registryUrl,
}: GetReleasesConfig): Promise<ReleaseResult | null> {
return await this.getByStream(
registryUrl,
packageName === 'm_EditorVersionWithRevision',
);
}
}
1 change: 1 addition & 0 deletions lib/util/cache/package/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export type PackageCacheNamespace =
| 'datasource-terraform-provider-zip-hashes'
| 'datasource-terraform-provider'
| 'datasource-terraform'
| 'datasource-unity3d'
| 'github-releases-datasource-v2'
| 'github-tags-datasource-v2'
| 'go'
Expand Down

0 comments on commit 29d3cd7

Please sign in to comment.