1 | import { DockerfileParser } from "dockerfile-ast";
|
2 | import { EOL } from "os";
|
3 | import { getDockerfileBaseImageName } from "./instruction-parser";
|
4 | import {
|
5 | UpdateDockerfileBaseImageNameErrorCode,
|
6 | UpdateDockerfileBaseImageNameResult,
|
7 | } from "./types";
|
8 |
|
9 | export { updateDockerfileBaseImageName };
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | function updateDockerfileBaseImageName(
|
17 | contents: string,
|
18 | newBaseImageName: string,
|
19 | ): UpdateDockerfileBaseImageNameResult {
|
20 | const dockerfile = DockerfileParser.parse(contents);
|
21 |
|
22 | const result = getDockerfileBaseImageName(dockerfile);
|
23 |
|
24 | if (result.error) {
|
25 | return {
|
26 | contents,
|
27 | error: {
|
28 | code: UpdateDockerfileBaseImageNameErrorCode.BASE_IMAGE_NAME_NOT_FOUND,
|
29 | },
|
30 | };
|
31 | }
|
32 |
|
33 | const currentBaseImageName = result.baseImage;
|
34 |
|
35 | const fromRanges = dockerfile
|
36 | .getFROMs()
|
37 | .filter((from) => from.getImage() === currentBaseImageName)
|
38 | .map((from) => from.getImageRange()!);
|
39 |
|
40 | const argRanges = dockerfile
|
41 | .getARGs()
|
42 | .filter((arg) => arg.getProperty()?.getValue() === currentBaseImageName)
|
43 | .map((arg) => arg.getProperty()?.getValueRange()!);
|
44 |
|
45 | const ranges = fromRanges.concat(argRanges);
|
46 |
|
47 | if (ranges.length === 0) {
|
48 | |
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | return {
|
57 | contents,
|
58 | error: {
|
59 | code: UpdateDockerfileBaseImageNameErrorCode.BASE_IMAGE_NAME_FRAGMENTED,
|
60 | },
|
61 | };
|
62 | }
|
63 |
|
64 | const lines = contents.split(EOL);
|
65 |
|
66 | for (const range of ranges) {
|
67 | const lineNumber = range.start.line;
|
68 | const start = range.start.character;
|
69 | const end = range.end.character;
|
70 |
|
71 | const content = lines[lineNumber];
|
72 | const updated =
|
73 | content.substring(0, start) + newBaseImageName + content.substring(end);
|
74 | lines[lineNumber] = updated;
|
75 | }
|
76 |
|
77 | const updatedContents = lines.join(EOL);
|
78 | const updatedDockerfile = DockerfileParser.parse(updatedContents);
|
79 |
|
80 | if (
|
81 | dockerfile.getInstructions().length !==
|
82 | updatedDockerfile.getInstructions().length
|
83 | ) {
|
84 | return {
|
85 | contents,
|
86 | error: {
|
87 | code: UpdateDockerfileBaseImageNameErrorCode.DOCKERFILE_GENERATION_FAILED,
|
88 | },
|
89 | };
|
90 | }
|
91 |
|
92 | return {
|
93 | contents: updatedContents,
|
94 | };
|
95 | }
|