Skip to content

Commit 3c07449

Browse files
Merge branch 'main' into dependabot/maven/dockerfile-image-update/org.sonatype.plugins-nexus-staging-maven-plugin-1.6.13
2 parents e498fa0 + 054443d commit 3c07449

File tree

10 files changed

+261
-36
lines changed

10 files changed

+261
-36
lines changed

.ci.prepare-ssh-gpg.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ openssl aes-256-cbc -K "${encrypted_96e73e3cb232_key}" -iv "${encrypted_96e73e3c
66
mkdir -p "${HOME}/.ssh"
77
mv -f id_rsa_dockerfile_image_update "${HOME}/.ssh/id_rsa"
88
chmod 600 "${HOME}/.ssh/id_rsa"
9-
echo "github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==" >> "${HOME}/.ssh/known_hosts"
9+
echo "github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=" >> "${HOME}/.ssh/known_hosts"
1010

1111
# Import code signing keys
1212
openssl aes-256-cbc -K "${encrypted_00fae8efff8c_key}" -iv "${encrypted_00fae8efff8c_iv}" -in codesigning.asc.enc -out codesigning.asc -d

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ named arguments:
141141
-s {true,false}, --skipprcreation {true,false}
142142
Only update image tag store. Skip creating PRs
143143
-x X comment snippet mentioned in line just before FROM instruction for ignoring a child image. Defaults to 'no-dfiu'
144-
-r, --rate-limit-pr-creations
144+
-r, --rate_limit_pr_creations
145145
Enable rateLimiting for throttling the number of PRs DFIU will cut over a period of time.
146-
The argument value should be in format "<positive_integer>-<ISO-8601_formatted_time>". For example "--rate-limit-pr-creations 60-PT1H" to create 60 PRs per hour.
146+
The argument value should be in format "<positive_integer>-<ISO-8601_formatted_time>". For example "--rate_limit_pr_creations 60-PT1H" to create 60 PRs per hour.
147147
Default is not set, this means no ratelimiting is imposed.
148148
149149
subcommands:
@@ -220,11 +220,11 @@ FROM imagename:imagetag # no-dfiu
220220
### PR throttling
221221

222222
In case you want to throttle the number of PRs cut by DFIU over a period of time,
223-
set --rate-limit-pr-creations with appropriate value.
223+
set --rate_limit_pr_creations with appropriate value.
224224

225225
##### Default case:
226226

227-
By default, this feature is disabled. This will be enabled when argument ``--rate-limit-pr-creations`` will be passed
227+
By default, this feature is disabled. This will be enabled when argument ``--rate_limit_pr_creations`` will be passed
228228
with appropriate value.
229229

230230
```
@@ -234,9 +234,9 @@ example: dockerfile-image-update all image-tag-store-repo-falcon //throttling wi
234234
##### Configuring the rate limit:
235235

236236
Below are some examples that will throttle the number of PRs cut based on values passed to the
237-
argument ``--rate-limit-pr-creations``
237+
argument ``--rate_limit_pr_creations``
238238
The argument value should be in format ``<positive_integer>-<ISO-8601_formatted_time>``.
239-
For example ``--rate-limit-pr-creations 60-PT1H`` would mean the tool will cut 60 PRs every hour and the rate of adding
239+
For example ``--rate_limit_pr_creations 60-PT1H`` would mean the tool will cut 60 PRs every hour and the rate of adding
240240
a new PR will be (PT1H/60) i.e. one minute.
241241
This will distribute the load uniformly and avoid sudden spikes, The process will go in waiting state until next PR
242242
could be sent.
@@ -245,11 +245,11 @@ Below are some more examples:
245245

246246
```
247247
Usage:
248-
dockerfile-image-update --rate-limit-pr-creations 60-PT1H all image-tag-store-repo-falcon //DFIU can send up to 60 PRs per hour.
249-
dockerfile-image-update --rate-limit-pr-creations 500-PT1H all image-tag-store-repo-falcon //DFIU can send up to 500 PRs per hour.
250-
dockerfile-image-update --rate-limit-pr-creations 86400-PT24H all image-tag-store-repo-falcon //DFIU can send up to 1 PRs per second.
251-
dockerfile-image-update --rate-limit-pr-creations 1-PT1S all image-tag-store-repo-falcon //Same as above. DFIU can send up to 1 PRs per second.
252-
dockerfile-image-update --rate-limit-pr-creations 5000 all image-tag-store-repo-falcon //rate limiting will be disabled because argument is not in correct format.
248+
dockerfile-image-update --rate_limit_pr_creations 60-PT1H all image-tag-store-repo-falcon //DFIU can send up to 60 PRs per hour.
249+
dockerfile-image-update --rate_limit_pr_creations 500-PT1H all image-tag-store-repo-falcon //DFIU can send up to 500 PRs per hour.
250+
dockerfile-image-update --rate_limit_pr_creations 86400-PT24H all image-tag-store-repo-falcon //DFIU can send up to 1 PRs per second.
251+
dockerfile-image-update --rate_limit_pr_creations 1-PT1S all image-tag-store-repo-falcon //Same as above. DFIU can send up to 1 PRs per second.
252+
dockerfile-image-update --rate_limit_pr_creations 5000 all image-tag-store-repo-falcon //rate limiting will be disabled because argument is not in correct format.
253253
```
254254

255255
## Developer Guide

dockerfile-image-update/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120
<dependency>
121121
<groupId>org.kohsuke</groupId>
122122
<artifactId>github-api</artifactId>
123-
<version>1.308</version>
123+
<version>1.315</version>
124124
</dependency>
125125
<dependency>
126126
<groupId>com.amazonaws</groupId>

dockerfile-image-update/src/main/java/com/salesforce/dockerfileimageupdate/CommandLine.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ static ArgumentParser getArgumentParser() {
9393
"(default: Dockerfile,docker-compose)");
9494
parser.addArgument("-r", "--" + RATE_LIMIT_PR_CREATION)
9595
.type(String.class)
96-
.setDefault("")
9796
.required(false)
9897
.help("Use RateLimiting when sending PRs. RateLimiting is enabled only if this value is set it's disabled by default.");
9998
return parser;

dockerfile-image-update/src/main/java/com/salesforce/dockerfileimageupdate/storage/S3BackedImageTagStore.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.amazonaws.services.s3.AmazonS3;
44
import com.amazonaws.services.s3.model.ListObjectsV2Result;
5+
import com.amazonaws.services.s3.model.ListObjectsV2Request;
56
import com.amazonaws.services.s3.model.S3Object;
67
import com.amazonaws.services.s3.model.S3ObjectInputStream;
78
import com.amazonaws.services.s3.model.S3ObjectSummary;
@@ -26,6 +27,7 @@ public class S3BackedImageTagStore implements ImageTagStore {
2627
private final AmazonS3 s3;
2728
private final String store;
2829

30+
2931
public S3BackedImageTagStore(AmazonS3 s3, @NonNull String store) {
3032
this.s3 = s3;
3133
this.store = store;
@@ -58,8 +60,7 @@ public void updateStore(String img, String tag) throws IOException {
5860
public List<ImageTagStoreContent> getStoreContent(DockerfileGitHubUtil dockerfileGitHubUtil, String storeName) throws InterruptedException {
5961
List<ImageTagStoreContent> imageNamesWithTag;
6062
Map<String, Date> imageNameWithAccessTime = new HashMap<>();
61-
ListObjectsV2Result result = getS3Objects();
62-
List<S3ObjectSummary> objects = result.getObjectSummaries();
63+
List<S3ObjectSummary> objects = getS3Objects();
6364
for (S3ObjectSummary os : objects) {
6465
Date lastModified = os.getLastModified();
6566
String key = os.getKey();
@@ -108,8 +109,21 @@ private String convertS3ObjectKeyToImageString(String key) {
108109
return key.replace(S3_FILE_KEY_PATH_DELIMITER, '/');
109110
}
110111

111-
private ListObjectsV2Result getS3Objects() {
112-
return s3.listObjectsV2(store);
112+
private List<S3ObjectSummary> getS3Objects() {
113+
ListObjectsV2Request request = new ListObjectsV2Request().withBucketName(store);
114+
ListObjectsV2Result listObjectsV2Result;
115+
List<S3ObjectSummary> objectSummaries = null;
116+
117+
do {
118+
listObjectsV2Result = s3.listObjectsV2(request);
119+
if (objectSummaries == null)
120+
objectSummaries = listObjectsV2Result.getObjectSummaries();
121+
else
122+
objectSummaries.addAll(listObjectsV2Result.getObjectSummaries());
123+
request.setContinuationToken(listObjectsV2Result.getNextContinuationToken());
124+
} while(listObjectsV2Result.isTruncated());
125+
126+
return objectSummaries;
113127
}
114128

115129
private S3Object getS3Object(String store, String key) {

dockerfile-image-update/src/main/java/com/salesforce/dockerfileimageupdate/utils/Constants.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ private Constants() {
4040
public static final String SKIP_PR_CREATION = "skipprcreation";
4141
public static final String IGNORE_IMAGE_STRING = "x";
4242
public static final String FILE_NAMES_TO_SEARCH = "filenamestosearch";
43-
public static final String RATE_LIMIT_PR_CREATION = "rate-limit-pr-creations";
43+
public static final String RATE_LIMIT_PR_CREATION = "rate_limit_pr_creations";
4444
//max number of PRs to be sent (or tokens to be added) per DEFAULT_RATE_LIMIT_DURATION(per hour in this case)
4545
public static final long DEFAULT_RATE_LIMIT = 60;
4646

4747
public static final long DEFAULT_CONSUMING_TOKEN_RATE = 1;
4848
public static final Duration DEFAULT_RATE_LIMIT_DURATION = Duration.ofMinutes(DEFAULT_RATE_LIMIT);
49-
//token adding rate(here:a token added every 2 minutes in the bucket)
49+
//token adding rate(here:a token added every 1 minutes in the bucket)
5050
public static final Duration DEFAULT_TOKEN_ADDING_RATE = Duration.ofMinutes(DEFAULT_CONSUMING_TOKEN_RATE);
5151
public static final String FILENAME_DOCKERFILE = "dockerfile";
5252
public static final String FILENAME_DOCKER_COMPOSE = "docker-compose";

dockerfile-image-update/src/main/java/com/salesforce/dockerfileimageupdate/utils/DockerfileGitHubUtil.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,14 +280,21 @@ public GHBlob tryRetrievingBlob(GHRepository repo, String path, String branch)
280280
public void modifyOnGithub(GHContent content,
281281
String branch, String img, String tag,
282282
String customMessage, String ignoreImageString) throws IOException {
283+
modifyContentOnGithub(content, branch, img, tag, customMessage, ignoreImageString);
284+
}
285+
286+
protected boolean modifyContentOnGithub(GHContent content,
287+
String branch, String img, String tag,
288+
String customMessage, String ignoreImageString) throws IOException {
283289
try (InputStream stream = content.read();
284290
InputStreamReader streamR = new InputStreamReader(stream);
285291
BufferedReader reader = new BufferedReader(streamR)) {
286-
findImagesAndFix(content, branch, img, tag, customMessage, reader, ignoreImageString);
292+
return findImagesAndFix(content, branch, img, tag, customMessage, reader,
293+
ignoreImageString);
287294
}
288295
}
289296

290-
protected void findImagesAndFix(GHContent content, String branch, String img,
297+
protected boolean findImagesAndFix(GHContent content, String branch, String img,
291298
String tag, String customMessage, BufferedReader reader,
292299
String ignoreImageString) throws IOException {
293300
StringBuilder strB = new StringBuilder();
@@ -296,6 +303,7 @@ protected void findImagesAndFix(GHContent content, String branch, String img,
296303
content.update(strB.toString(),
297304
"Fix Docker base image in /" + content.getPath() + "\n\n" + customMessage, branch);
298305
}
306+
return modified;
299307
}
300308

301309
protected boolean rewriteDockerfile(String img, String tag,
@@ -542,9 +550,10 @@ public void changeDockerfiles(Namespace ns,
542550
if (content == null) {
543551
log.info("No Dockerfile found at path: '{}'", pathToDockerfile);
544552
} else {
545-
modifyOnGithub(content, gitForkBranch.getBranchName(), gitForkBranch.getImageName(), gitForkBranch.getImageTag(),
546-
ns.get(Constants.GIT_ADDITIONAL_COMMIT_MESSAGE), ns.get(Constants.IGNORE_IMAGE_STRING));
547-
isContentModified = true;
553+
isContentModified |= modifyContentOnGithub(content, gitForkBranch.getBranchName(),
554+
gitForkBranch.getImageName(), gitForkBranch.getImageTag(),
555+
ns.get(Constants.GIT_ADDITIONAL_COMMIT_MESSAGE),
556+
ns.get(Constants.IGNORE_IMAGE_STRING));
548557
isRepoSkipped = false;
549558
}
550559
}
@@ -567,6 +576,8 @@ public void changeDockerfiles(Namespace ns,
567576
forkedRepo,
568577
pullRequestInfo,
569578
rateLimiter);
579+
} else {
580+
log.info("No files changed in repo {}. Skipping PR creation attempt.", parentName);
570581
}
571582
}
572583

dockerfile-image-update/src/main/java/com/salesforce/dockerfileimageupdate/utils/GitHubUtil.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public int createPullReq(GHRepository origRepo, String branch,
105105
try {
106106
GHPullRequest pullRequest = origRepo.createPullRequest(title, forkRepo.getOwnerName() + ":" + branch,
107107
origRepo.getDefaultBranch(), body);
108+
pullRequest.setLabels("dependencies");
108109
// origRepo.createPullRequest("Update base image in Dockerfile", forkRepo.getOwnerName() + ":" + branch,
109110
// origRepo.getDefaultBranch(), "Automatic Dockerfile Image Updater. Please merge.");
110111
log.info("A pull request has been created at {}", pullRequest.getHtmlUrl());

dockerfile-image-update/src/test/java/com/salesforce/dockerfileimageupdate/storage/S3BackedImageTagStoreTest.java

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package com.salesforce.dockerfileimageupdate.storage;
22

3+
34
import com.amazonaws.services.s3.AmazonS3;
45
import com.amazonaws.services.s3.model.ListObjectsV2Result;
6+
import com.amazonaws.services.s3.model.ListObjectsV2Request;
57
import com.amazonaws.services.s3.model.S3Object;
68
import com.amazonaws.services.s3.model.S3ObjectInputStream;
79
import com.amazonaws.services.s3.model.S3ObjectSummary;
810
import com.salesforce.dockerfileimageupdate.utils.DockerfileGitHubUtil;
911
import org.testng.annotations.Test;
12+
import static org.mockito.ArgumentMatchers.any;
1013

1114
import java.io.ByteArrayInputStream;
1215
import java.io.IOException;
@@ -36,12 +39,60 @@ public void testUpdateStoreThrowsExceptionWhenBucketDoesNotExist() throws IOExce
3639
verify(amazonS3, times(0)).putObject("store", "image", "tag");
3740
}
3841

42+
@Test
43+
public void testGetStoreContentReturnsStoreContentWithTruncatedResults() throws InterruptedException {
44+
AmazonS3 amazonS3 = mock(AmazonS3.class);
45+
S3BackedImageTagStore s3BackedImageTagStore = spy(new S3BackedImageTagStore(amazonS3, "store"));
46+
DockerfileGitHubUtil dockerfileGitHubUtil = mock(DockerfileGitHubUtil.class);
47+
ListObjectsV2Result listObjectsV2Result1 = mock(ListObjectsV2Result.class);
48+
ListObjectsV2Result listObjectsV2Result2 = mock(ListObjectsV2Result.class);
49+
50+
S3ObjectSummary s3ObjectSummary = mock(S3ObjectSummary.class);
51+
List<S3ObjectSummary> s3ObjectSummaryList = new ArrayList<>();
52+
s3ObjectSummaryList.add(s3ObjectSummary);
53+
54+
Date date = mock(Date.class);
55+
S3Object s3Object = mock(S3Object.class);
56+
S3Object s3Object2 = mock(S3Object.class);
57+
String tag = "tag";
58+
String tag2 = "tag2";
59+
byte tagBytes[] = tag.getBytes();
60+
byte tagBytes2[] = tag2.getBytes();
61+
S3ObjectInputStream objectContent = new S3ObjectInputStream(new ByteArrayInputStream(tagBytes), null);
62+
S3ObjectInputStream objectContent2 = new S3ObjectInputStream(new ByteArrayInputStream(tagBytes2), null);
63+
s3Object.setObjectContent(objectContent);
64+
s3Object2.setObjectContent(objectContent2);
65+
66+
when(amazonS3.listObjectsV2(any(ListObjectsV2Request.class))).thenReturn(listObjectsV2Result1, listObjectsV2Result2);
67+
when(listObjectsV2Result1.getObjectSummaries()).thenReturn(s3ObjectSummaryList);
68+
when(listObjectsV2Result1.isTruncated()).thenReturn(true);
69+
when(listObjectsV2Result2.getObjectSummaries()).thenReturn(s3ObjectSummaryList);
70+
when(listObjectsV2Result2.isTruncated()).thenReturn(false);
71+
when(s3ObjectSummary.getLastModified()).thenReturn(date , date);
72+
when(s3ObjectSummary.getKey()).thenReturn("domain!namespace!image", "domain!namespace!image2");
73+
when(amazonS3.getObject("store", "domain!namespace!image")).thenReturn(s3Object);
74+
when(amazonS3.getObject("store", "domain!namespace!image2")).thenReturn(s3Object2);
75+
when(s3Object.getObjectContent()).thenReturn(objectContent);
76+
when(s3Object2.getObjectContent()).thenReturn(objectContent2);
77+
78+
List<ImageTagStoreContent> actualResult = s3BackedImageTagStore.getStoreContent(dockerfileGitHubUtil, "store");
79+
80+
verify(amazonS3).getObject("store", "domain!namespace!image");
81+
verify(amazonS3).getObject("store", "domain!namespace!image2");
82+
assertEquals(actualResult.size(), 2);
83+
assertEquals(actualResult.get(0).getImageName(), "domain/namespace/image");
84+
assertEquals(actualResult.get(0).getTag(), "tag");
85+
assertEquals(actualResult.get(1).getImageName(), "domain/namespace/image2");
86+
assertEquals(actualResult.get(1).getTag(), "tag2");
87+
}
88+
3989
@Test
4090
public void testGetStoreContentReturnsStoreContent() throws InterruptedException {
4191
AmazonS3 amazonS3 = mock(AmazonS3.class);
4292
S3BackedImageTagStore s3BackedImageTagStore = spy(new S3BackedImageTagStore(amazonS3, "store"));
4393
DockerfileGitHubUtil dockerfileGitHubUtil = mock(DockerfileGitHubUtil.class);
4494
ListObjectsV2Result listObjectsV2Result = mock(ListObjectsV2Result.class);
95+
4596
S3ObjectSummary s3ObjectSummary = mock(S3ObjectSummary.class);
4697
List<S3ObjectSummary> s3ObjectSummaryListList = Collections.singletonList(s3ObjectSummary);
4798
Date date = mock(Date.class);
@@ -51,8 +102,9 @@ public void testGetStoreContentReturnsStoreContent() throws InterruptedException
51102
S3ObjectInputStream objectContent = new S3ObjectInputStream(new ByteArrayInputStream(tagBytes), null);
52103
s3Object.setObjectContent(objectContent);
53104

54-
when(amazonS3.listObjectsV2("store")).thenReturn(listObjectsV2Result);
105+
when(amazonS3.listObjectsV2(any(ListObjectsV2Request.class))).thenReturn(listObjectsV2Result);
55106
when(listObjectsV2Result.getObjectSummaries()).thenReturn(s3ObjectSummaryListList);
107+
when(listObjectsV2Result.isTruncated()).thenReturn(false);
56108
when(s3ObjectSummary.getLastModified()).thenReturn(date);
57109
when(s3ObjectSummary.getKey()).thenReturn("domain!namespace!image");
58110
when(amazonS3.getObject("store", "domain!namespace!image")).thenReturn(s3Object);
@@ -97,8 +149,9 @@ public void testGetStoreContentReturnsStoreContentSorted() throws InterruptedExc
97149
when(s3ObjectSummaryIterator.next()).thenReturn(s3ObjectSummary, s3ObjectSummary);
98150
when(s3ObjectSummaryIterator.hasNext()).thenReturn(true, true, false);
99151
when(s3ObjectSummaryList.iterator()).thenReturn(s3ObjectSummaryIterator);
100-
when(amazonS3.listObjectsV2("store")).thenReturn(listObjectsV2Result);
152+
when(amazonS3.listObjectsV2(any(ListObjectsV2Request.class))).thenReturn(listObjectsV2Result);
101153
when(listObjectsV2Result.getObjectSummaries()).thenReturn(s3ObjectSummaryList);
154+
when(listObjectsV2Result.isTruncated()).thenReturn(false);
102155
when(s3ObjectSummary.getLastModified()).thenReturn(date1, date2);
103156
when(s3ObjectSummary.getKey()).thenReturn(key1, key2);
104157
when(amazonS3.getObject("store", key1)).thenReturn(s3Object1);

0 commit comments

Comments
 (0)