forked from renovatebot/renovate
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.ts
123 lines (115 loc) · 3.34 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { logger } from '../../logger';
import { ExternalHostError } from '../../types/errors/external-host-error';
import * as packageCache from '../../util/cache/package';
import { Http } from '../../util/http';
import { GetReleasesConfig, ReleaseResult } from '../common';
export const id = 'terraform-module';
export const defaultRegistryUrls = ['https://registry.terraform.io'];
export const registryStrategy = 'first';
const http = new Http(id);
interface RegistryRepository {
registry: string;
repository: string;
}
function getRegistryRepository(
lookupName: string,
registryUrl: string
): RegistryRepository {
let registry: string;
const split = lookupName.split('/');
if (split.length > 3 && split[0].includes('.')) {
[registry] = split;
split.shift();
} else {
registry = registryUrl;
}
if (!/^https?:\/\//.test(registry)) {
registry = `https://${registry}`;
}
const repository = split.join('/');
return {
registry,
repository,
};
}
interface TerraformRelease {
namespace: string;
name: string;
provider: string;
source?: string;
versions: string[];
}
export interface ServiceDiscoveryResult {
'modules.v1'?: string;
'providers.v1'?: string;
}
/**
* terraform.getReleases
*
* This function will fetch a package from the specified Terraform registry and return all semver versions.
* - `sourceUrl` is supported of "source" field is set
* - `homepage` is set to the Terraform registry's page if it's on the official main registry
*/
export async function getReleases({
lookupName,
registryUrl,
}: GetReleasesConfig): Promise<ReleaseResult | null> {
const { registry, repository } = getRegistryRepository(
lookupName,
registryUrl
);
logger.debug(
{ registry, terraformRepository: repository },
'terraform.getDependencies()'
);
const cacheNamespace = 'terraform-module';
const cacheURL = `${registry}/${repository}`;
const cachedResult = await packageCache.get<ReleaseResult>(
cacheNamespace,
cacheURL
);
// istanbul ignore if
if (cachedResult) {
return cachedResult;
}
try {
const serviceDiscovery = (
await http.getJson<ServiceDiscoveryResult>(
`${registryUrl}/.well-known/terraform.json`
)
).body;
const pkgUrl = `${registry}${serviceDiscovery['modules.v1']}${repository}`;
const res = (await http.getJson<TerraformRelease>(pkgUrl)).body;
const returnedName = res.namespace + '/' + res.name + '/' + res.provider;
if (returnedName !== repository) {
logger.warn({ pkgUrl }, 'Terraform registry result mismatch');
return null;
}
// Simplify response before caching and returning
const dep: ReleaseResult = {
name: repository,
versions: {},
releases: null,
};
if (res.source) {
dep.sourceUrl = res.source;
}
dep.releases = res.versions.map((version) => ({
version,
}));
if (pkgUrl.startsWith('https://registry.terraform.io/')) {
dep.homepage = `https://registry.terraform.io/modules/${repository}`;
}
logger.trace({ dep }, 'dep');
const cacheMinutes = 30;
await packageCache.set(cacheNamespace, pkgUrl, dep, cacheMinutes);
return dep;
} catch (err) {
const failureCodes = ['EAI_AGAIN'];
// istanbul ignore if
if (failureCodes.includes(err.code)) {
throw new ExternalHostError(err);
}
throw err;
}
}