Skip to content

Commit d7b0c16

Browse files
authored
Merge branch 'main' into feature/add-path-prefix-ignore
2 parents 80be517 + 0b83e45 commit d7b0c16

File tree

11 files changed

+289
-224
lines changed

11 files changed

+289
-224
lines changed

.github/dependabot.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ updates:
1717
day: 'monday'
1818
time: '08:00'
1919
groups:
20+
eslint:
21+
patterns:
22+
- 'eslint'
23+
- '@eslint/*'
24+
- 'typescript-eslint'
2025
eui:
2126
patterns:
2227
- '@elastic/eui*'

Directory.Packages.props

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
<PackageVersion Include="Amazon.Lambda.S3Events" Version="3.1.0" />
1414
<PackageVersion Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.4" />
1515
<PackageVersion Include="Amazon.Lambda.SQSEvents" Version="2.2.0" />
16-
<PackageVersion Include="AWSSDK.CloudFront" Version="4.0.0.10" />
17-
<PackageVersion Include="AWSSDK.CloudFrontKeyValueStore" Version="4.0.0.9" />
1816
<PackageVersion Include="AWSSDK.Core" Version="4.0.0.2" />
1917
<PackageVersion Include="AWSSDK.SQS" Version="4.0.0.1" />
2018
<PackageVersion Include="AWSSDK.S3" Version="4.0.0.1" />

docs/migration/guide/mapping.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ navigation_title: What books were migrated?
66

77
We did not migrate all Elastic documentation. We are purposefully leaving the majority of content behind in the legacy Asciidoc build system. This system will turn into our documentation archive.
88

9-
A full list of the content that was migrated to the V3 format is available [here](https://github.com/elastic/asciidocalypse/blob/main/docs/readme.md).
9+
A full list of the content that was migrated to the V3 format is available [here](https://github.com/elastic/asciidocalypse/tree/main-archive/docs#readme).

docs/migration/versioning.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Tagged deployment
4747

4848
This is the default. To get started, follow our [guide](guide/index.md) to set up the new docs folder structure and CI configuration
4949

50-
Once setup ensure the repository is added to our `assembler.yml` under `references`.
50+
Once setup ensure the repository is added to our [`assembler.yml`](https://github.com/elastic/docs-builder/blob/main/src/tooling/docs-assembler/assembler.yml) under `references`.
5151

5252
For example say you want to onboard `elastic/my-repository` into the production build:
5353

@@ -113,4 +113,4 @@ jobs:
113113
pull-requests: read
114114
```
115115

116-
1. Ensure version branches are built and publish their links ahead of time.
116+
1. Ensure version branches are built and publish their links ahead of time.

src/Elastic.Documentation.Site/package-lock.json

Lines changed: 94 additions & 126 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Elastic.Documentation.Site/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@
2828
"private": true,
2929
"devDependencies": {
3030
"@elastic/datemath": "5.0.3",
31-
"@elastic/eui": "104.0.2",
32-
"@elastic/eui-theme-borealis": "3.0.0",
31+
"@elastic/eui": "104.1.0",
32+
"@elastic/eui-theme-borealis": "3.1.0",
3333
"@emotion/css": "11.13.5",
3434
"@emotion/react": "11.14.0",
35-
"@eslint/js": "9.30.0",
35+
"@eslint/js": "9.30.1",
3636
"@r2wc/react-to-web-component": "2.0.4",
3737
"@tailwindcss/postcss": "4.1.11",
3838
"@trivago/prettier-plugin-sort-imports": "5.2.2",
39-
"eslint": "9.30.0",
40-
"globals": "16.2.0",
39+
"eslint": "9.30.1",
40+
"globals": "16.3.0",
4141
"moment": "2.30.1",
4242
"parcel": "2.15.4",
4343
"postcss": "8.5.6",
@@ -46,7 +46,7 @@
4646
"prettier-plugin-tailwindcss": "0.6.13",
4747
"react": "18.3.1",
4848
"react-dom": "18.3.1",
49-
"typescript-eslint": "8.35.0"
49+
"typescript-eslint": "8.35.1"
5050
},
5151
"browserslist": [
5252
"defaults"

src/tooling/Elastic.Documentation.Tooling/ExternalCommands/ExternalCommandExecutor.cs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
using System.IO.Abstractions;
66
using Elastic.Documentation.Diagnostics;
77
using ProcNet;
8-
using ProcNet.Std;
98

109
namespace Elastic.Documentation.Tooling.ExternalCommands;
1110

1211
public abstract class ExternalCommandExecutor(DiagnosticsCollector collector, IDirectoryInfo workingDirectory)
1312
{
1413
protected IDirectoryInfo WorkingDirectory => workingDirectory;
14+
protected DiagnosticsCollector Collector => collector;
1515
protected void ExecIn(Dictionary<string, string> environmentVars, string binary, params string[] args)
1616
{
1717
var arguments = new ExecArguments(binary, args)
@@ -37,11 +37,12 @@ protected void ExecInSilent(Dictionary<string, string> environmentVars, string b
3737
collector.EmitError("", $"Exit code: {result.ExitCode} while executing {binary} {string.Join(" ", args)} in {workingDirectory}");
3838
}
3939

40-
protected string[] CaptureMultiple(string binary, params string[] args)
40+
protected string[] CaptureMultiple(string binary, params string[] args) => CaptureMultiple(false, 10, binary, args);
41+
protected string[] CaptureMultiple(bool muteExceptions, int attempts, string binary, params string[] args)
4142
{
4243
// Try 10 times to capture the output of the command, if it fails, we'll throw an exception on the last try
4344
Exception? e = null;
44-
for (var i = 0; i <= 9; i++)
45+
for (var i = 1; i <= attempts; i++)
4546
{
4647
try
4748
{
@@ -54,7 +55,7 @@ protected string[] CaptureMultiple(string binary, params string[] args)
5455
}
5556
}
5657

57-
if (e is not null)
58+
if (e is not null && !muteExceptions)
5859
collector.EmitError("", "failure capturing stdout", e);
5960

6061
return [];
@@ -69,21 +70,24 @@ string[] CaptureOutput()
6970
ConsoleOutWriter = NoopConsoleWriter.Instance
7071
};
7172
var result = Proc.Start(arguments);
72-
var output = result.ExitCode != 0
73-
? throw new Exception($"Exit code is not 0. Received {result.ExitCode} from {binary}: {workingDirectory}")
74-
: result.ConsoleOut.Select(x => x.Line).ToArray() ?? throw new Exception($"No output captured for {binary}: {workingDirectory}");
73+
74+
var output = (result.ExitCode, muteExceptions) switch
75+
{
76+
(0, _) or (not 0, true) => result.ConsoleOut.Select(x => x.Line).ToArray() ?? throw new Exception($"No output captured for {binary}: {workingDirectory}"),
77+
(not 0, false) => throw new Exception($"Exit code is not 0. Received {result.ExitCode} from {binary}: {workingDirectory}")
78+
};
7579
return output;
7680
}
7781
}
7882

7983

80-
protected string Capture(string binary, params string[] args) => Capture(false, binary, args);
81-
82-
protected string Capture(bool muteExceptions, string binary, params string[] args)
84+
protected string Capture(string binary, params string[] args) => Capture(false, 10, binary, args);
85+
protected string Capture(bool muteExceptions, string binary, params string[] args) => Capture(muteExceptions, 10, binary, args);
86+
protected string Capture(bool muteExceptions, int attempts, string binary, params string[] args)
8387
{
8488
// Try 10 times to capture the output of the command, if it fails, we'll throw an exception on the last try
8589
Exception? e = null;
86-
for (var i = 0; i <= 9; i++)
90+
for (var i = 1; i <= attempts; i++)
8791
{
8892
try
8993
{

src/tooling/docs-assembler/Cli/DeployCommands.cs

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
using System.IO.Abstractions;
77
using System.Text.Json;
88
using Actions.Core.Services;
9-
using Amazon.CloudFront;
10-
using Amazon.CloudFrontKeyValueStore;
11-
using Amazon.CloudFrontKeyValueStore.Model;
129
using Amazon.S3;
1310
using Amazon.S3.Transfer;
1411
using ConsoleAppFramework;
@@ -20,12 +17,6 @@
2017

2118
namespace Documentation.Assembler.Cli;
2219

23-
internal enum KvsOperation
24-
{
25-
Puts,
26-
Deletes
27-
}
28-
2920
internal sealed class DeployCommands(ILoggerFactory logger, ICoreService githubActionsService)
3021
{
3122
[SuppressMessage("Usage", "CA2254:Template should be a static expression")]
@@ -144,74 +135,11 @@ public async Task<int> UpdateRedirects(
144135
}
145136

146137
var kvsName = $"elastic-docs-v3-{environment}-redirects-kvs";
138+
var cloudFrontClient = new AwsCloudFrontKeyValueStoreProxy(collector, new FileSystem().DirectoryInfo.New(Directory.GetCurrentDirectory()));
147139

148-
var cfClient = new AmazonCloudFrontClient();
149-
var kvsClient = new AmazonCloudFrontKeyValueStoreClient();
150-
151-
ConsoleApp.Log("Describing KVS");
152-
var describeResponse = await cfClient.DescribeKeyValueStoreAsync(new Amazon.CloudFront.Model.DescribeKeyValueStoreRequest { Name = kvsName }, ctx);
153-
154-
var kvsArn = describeResponse.KeyValueStore.ARN;
155-
var eTag = describeResponse.ETag;
156-
var existingRedirects = new HashSet<string>();
157-
158-
var listKeysRequest = new ListKeysRequest { KvsARN = kvsArn };
159-
ListKeysResponse listKeysResponse;
160-
161-
do
162-
{
163-
listKeysResponse = await kvsClient.ListKeysAsync(listKeysRequest, ctx);
164-
foreach (var item in listKeysResponse.Items)
165-
_ = existingRedirects.Add(item.Key);
166-
listKeysRequest.NextToken = listKeysResponse.NextToken;
167-
}
168-
while (!string.IsNullOrEmpty(listKeysResponse.NextToken));
169-
170-
var toPut = sourcedRedirects
171-
.Select(kvp => new PutKeyRequestListItem { Key = kvp.Key, Value = kvp.Value });
172-
var toDelete = existingRedirects
173-
.Except(sourcedRedirects.Keys)
174-
.Select(k => new DeleteKeyRequestListItem { Key = k });
175-
176-
ConsoleApp.Log("Updating redirects in KVS");
177-
const int batchSize = 50;
178-
179-
eTag = await ProcessBatchUpdatesAsync(kvsClient, kvsArn, eTag, toPut, batchSize, KvsOperation.Puts, ctx);
180-
_ = await ProcessBatchUpdatesAsync(kvsClient, kvsArn, eTag, toDelete, batchSize, KvsOperation.Deletes, ctx);
140+
cloudFrontClient.UpdateRedirects(kvsName, sourcedRedirects);
181141

182142
await collector.StopAsync(ctx);
183143
return collector.Errors;
184144
}
185-
186-
private static async Task<string> ProcessBatchUpdatesAsync(
187-
IAmazonCloudFrontKeyValueStore kvsClient,
188-
string kvsArn,
189-
string eTag,
190-
IEnumerable<object> items,
191-
int batchSize,
192-
KvsOperation operation,
193-
Cancel ctx)
194-
{
195-
var enumerable = items.ToList();
196-
for (var i = 0; i < enumerable.Count; i += batchSize)
197-
{
198-
var batch = enumerable.Skip(i).Take(batchSize);
199-
var updateRequest = new UpdateKeysRequest
200-
{
201-
KvsARN = kvsArn,
202-
IfMatch = eTag
203-
};
204-
205-
if (operation is KvsOperation.Puts)
206-
updateRequest.Puts = batch.Cast<PutKeyRequestListItem>().ToList();
207-
else if (operation is KvsOperation.Deletes)
208-
updateRequest.Deletes = batch.Cast<DeleteKeyRequestListItem>().ToList();
209-
210-
var update = await kvsClient.UpdateKeysAsync(updateRequest, ctx);
211-
eTag = update.ETag;
212-
}
213-
214-
return eTag;
215-
}
216-
217145
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.IO.Abstractions;
6+
using System.Text.Json;
7+
using ConsoleAppFramework;
8+
using Documentation.Assembler.Deploying.Serialization;
9+
using Elastic.Documentation.Diagnostics;
10+
using Elastic.Documentation.Tooling.ExternalCommands;
11+
12+
namespace Documentation.Assembler.Deploying;
13+
14+
internal enum KvsOperation
15+
{
16+
Puts,
17+
Deletes
18+
}
19+
20+
public class AwsCloudFrontKeyValueStoreProxy(DiagnosticsCollector collector, IDirectoryInfo workingDirectory) : ExternalCommandExecutor(collector, workingDirectory)
21+
{
22+
public void UpdateRedirects(string kvsName, IReadOnlyDictionary<string, string> sourcedRedirects)
23+
{
24+
var (kvsArn, eTag) = DescribeKeyValueStore(kvsName);
25+
if (string.IsNullOrEmpty(kvsArn) || string.IsNullOrEmpty(eTag))
26+
return;
27+
28+
var existingRedirects = ListAllKeys(kvsArn);
29+
30+
var toPut = sourcedRedirects
31+
.Select(kvp => new PutKeyRequestListItem { Key = kvp.Key, Value = kvp.Value });
32+
var toDelete = existingRedirects
33+
.Except(sourcedRedirects.Keys)
34+
.Select(k => new DeleteKeyRequestListItem { Key = k });
35+
36+
eTag = ProcessBatchUpdates(kvsArn, eTag, toPut, KvsOperation.Puts);
37+
_ = ProcessBatchUpdates(kvsArn, eTag, toDelete, KvsOperation.Deletes);
38+
}
39+
40+
private (string? Arn, string? ETag) DescribeKeyValueStore(string kvsName)
41+
{
42+
ConsoleApp.Log("Describing KeyValueStore");
43+
try
44+
{
45+
var json = CaptureMultiple("aws", "cloudfront", "describe-key-value-store", "--name", kvsName);
46+
var describeResponse = JsonSerializer.Deserialize<DescribeKeyValueStoreResponse>(string.Concat(json), AwsCloudFrontKeyValueStoreJsonContext.Default.DescribeKeyValueStoreResponse);
47+
if (describeResponse?.ETag is not null && describeResponse.KeyValueStore is { ARN.Length: > 0 })
48+
return (describeResponse.KeyValueStore.ARN, describeResponse.ETag);
49+
50+
Collector.EmitError("", "Could not deserialize the DescribeKeyValueStoreResponse");
51+
return (null, null);
52+
}
53+
catch (Exception e)
54+
{
55+
Collector.EmitError("", "An error occurred while describing the KeyValueStore", e);
56+
return (null, null);
57+
}
58+
}
59+
60+
private HashSet<string> ListAllKeys(string kvsArn)
61+
{
62+
ConsoleApp.Log("Acquiring existing redirects");
63+
var allKeys = new HashSet<string>();
64+
string[] baseArgs = ["cloudfront-keyvaluestore", "list-keys", "--kvs-arn", kvsArn];
65+
string? nextToken = null;
66+
try
67+
{
68+
do
69+
{
70+
var json = CaptureMultiple("aws", [.. baseArgs, .. nextToken is not null ? (string[])["--starting-token", nextToken] : []]);
71+
var response = JsonSerializer.Deserialize<ListKeysResponse>(string.Concat(json), AwsCloudFrontKeyValueStoreJsonContext.Default.ListKeysResponse);
72+
73+
if (response?.Items != null)
74+
{
75+
foreach (var item in response.Items)
76+
_ = allKeys.Add(item.Key);
77+
}
78+
79+
nextToken = response?.NextToken;
80+
} while (!string.IsNullOrEmpty(nextToken));
81+
}
82+
catch (Exception e)
83+
{
84+
Collector.EmitError("", "An error occurred while acquiring existing redirects in the KeyValueStore", e);
85+
return [];
86+
}
87+
return allKeys;
88+
}
89+
90+
91+
private string ProcessBatchUpdates(
92+
string kvsArn,
93+
string eTag,
94+
IEnumerable<object> items,
95+
KvsOperation operation)
96+
{
97+
const int batchSize = 50;
98+
ConsoleApp.Log($"Processing {items.Count()} items in batches of {batchSize} for {operation} update operation.");
99+
try
100+
{
101+
foreach (var batch in items.Chunk(batchSize))
102+
{
103+
var payload = operation switch
104+
{
105+
KvsOperation.Puts => JsonSerializer.Serialize(batch.Cast<PutKeyRequestListItem>().ToList(),
106+
AwsCloudFrontKeyValueStoreJsonContext.Default.ListPutKeyRequestListItem),
107+
KvsOperation.Deletes => JsonSerializer.Serialize(batch.Cast<DeleteKeyRequestListItem>().ToList(),
108+
AwsCloudFrontKeyValueStoreJsonContext.Default.ListDeleteKeyRequestListItem),
109+
_ => string.Empty
110+
};
111+
var responseJson = CaptureMultiple(false, 1, "aws", "cloudfront-keyvaluestore", "update-keys", "--kvs-arn", kvsArn, "--if-match", eTag,
112+
$"--{operation.ToString().ToLowerInvariant()}", payload);
113+
var updateResponse = JsonSerializer.Deserialize<UpdateKeysResponse>(string.Concat(responseJson), AwsCloudFrontKeyValueStoreJsonContext.Default.UpdateKeysResponse);
114+
115+
if (string.IsNullOrEmpty(updateResponse?.ETag))
116+
throw new Exception("Failed to get new ETag after update operation.");
117+
118+
eTag = updateResponse.ETag;
119+
}
120+
}
121+
catch (Exception e)
122+
{
123+
Collector.EmitError("", $"An error occurred while performing a {operation} update to the KeyValueStore", e);
124+
}
125+
return eTag;
126+
}
127+
}

0 commit comments

Comments
 (0)