Skip to content

Commit c222dc0

Browse files
authored
PRPr 111 (#112)
* add onedrive google drive and dropbox providers * implement onedrive graph client and docs * more work and fixes * client * code + docs * fixes
1 parent 68a37b5 commit c222dc0

File tree

168 files changed

+13278
-750
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

168 files changed

+13278
-750
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ env:
1010
DOTNET_VERSION: '10.0.x'
1111

1212
jobs:
13-
build:
14-
name: Build and Test
13+
build-and-test:
14+
name: build-and-test
1515
runs-on: ubuntu-latest
1616

1717
steps:
Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
name: Docs (GitHub Pages)
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- README.md
8+
- docs/**
9+
- github-pages/**
10+
- .github/workflows/jekyll-gh-pages.yml
11+
workflow_dispatch:
12+
13+
permissions:
14+
contents: read
15+
pages: write
16+
id-token: write
17+
18+
concurrency:
19+
group: pages
20+
cancel-in-progress: false
21+
22+
jobs:
23+
build:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Checkout
27+
uses: actions/checkout@v5
28+
29+
- name: Add version and build date
30+
run: |
31+
echo "version: \"${{ github.run_number }}\"" >> github-pages/_config.yml
32+
echo "build_date: \"$(date +'%Y-%m-%d')\"" >> github-pages/_config.yml
33+
34+
- name: Generate site pages from docs
35+
run: |
36+
set -euo pipefail
37+
38+
rewrite_md_links() {
39+
# Rewrite *.md links to *.html for the rendered site (keep source docs GitHub-friendly).
40+
# Only rewrites relative links (no ':' in the target) so external URLs are untouched.
41+
sed -E \
42+
-e 's|\]\(README\.md\)|](/)|g' \
43+
-e 's|\]\(([^):]+)\.md(#[^)]*)?\)|](\1.html\2)|g'
44+
}
45+
46+
extract_description() {
47+
# Grab the first meaningful paragraph (skips headings, code fences, and bullet lists).
48+
awk '
49+
BEGIN { in_code=0 }
50+
/^```/ { in_code = !in_code; next }
51+
in_code { next }
52+
NR == 1 { next } # skip H1
53+
/^[[:space:]]*$/ { next } # skip blanks
54+
/^#/ { next } # skip headings
55+
/^(Accepted|Proposed|Rejected|Superseded|Deprecated)[[:space:]]/ { next } # skip ADR status line
56+
/^[[:space:]]*[-*]/ { next } # skip bullets
57+
{ print; exit }
58+
'
59+
}
60+
61+
keywords_for_feature() {
62+
case "$1" in
63+
storage-core.md) echo "IStorage, ManagedCode.Storage.Core, provider-agnostic storage, upload, download, streaming, metadata, Result<T>, .NET" ;;
64+
dependency-injection.md) echo "dependency injection, keyed services, IServiceCollection, IStorage, multi-tenant storage, .NET" ;;
65+
virtual-file-system.md) echo "virtual file system, IVirtualFileSystem, overlay, metadata cache, ManagedCode.Storage.VirtualFileSystem, .NET" ;;
66+
mime-and-crc.md) echo "MimeHelper, content-type, CRC32, integrity, ManagedCode.MimeTypes, ManagedCode.Storage.Core" ;;
67+
testfakes.md) echo "test fakes, provider doubles, Testcontainers, integration tests, ManagedCode.Storage.TestFakes" ;;
68+
integration-aspnet-server.md) echo "ASP.NET storage controller, streaming upload, ranged download, SignalR hub, ManagedCode.Storage.Server" ;;
69+
integration-dotnet-client.md) echo ".NET HTTP client, StorageClient, upload, download, chunked upload, CRC32, ManagedCode.Storage.Client" ;;
70+
integration-signalr-client.md) echo "SignalR client, streaming, upload, download, progress, StorageSignalRClient, ManagedCode.Storage.Client.SignalR" ;;
71+
chunked-uploads.md) echo "chunked uploads, resumable upload, CRC32, ASP.NET, ManagedCode.Storage.Server, ManagedCode.Storage.Client" ;;
72+
provider-azure-blob.md) echo "Azure Blob Storage, ManagedCode.Storage.Azure, IStorage, BlobClient, container, streaming upload, download, .NET" ;;
73+
provider-azure-datalake.md) echo "Azure Data Lake Gen2, ADLS, ManagedCode.Storage.Azure.DataLake, IStorage, filesystem, directory, .NET" ;;
74+
provider-aws-s3.md) echo "Amazon S3, AWS S3, ManagedCode.Storage.Aws, IStorage, bucket, streaming upload, Object Lock, legal hold, .NET" ;;
75+
provider-google-cloud-storage.md) echo "Google Cloud Storage, GCS, ManagedCode.Storage.Gcp, StorageClient, IStorage, bucket, streaming, .NET" ;;
76+
provider-filesystem.md) echo "file system storage, local development, ManagedCode.Storage.FileSystem, IStorage, tests, .NET" ;;
77+
provider-sftp.md) echo "SFTP storage, SSH.NET, ManagedCode.Storage.Sftp, IStorage, upload, download, .NET" ;;
78+
provider-onedrive.md) echo "OneDrive, Microsoft Graph, GraphServiceClient, Entra ID, OAuth, ManagedCode.Storage.OneDrive, IStorage, .NET" ;;
79+
provider-googledrive.md) echo "Google Drive API, DriveService, OAuth, service account, ManagedCode.Storage.GoogleDrive, IStorage, .NET" ;;
80+
provider-dropbox.md) echo "Dropbox API, DropboxClient, OAuth2, refresh token, ManagedCode.Storage.Dropbox, IStorage, .NET" ;;
81+
provider-cloudkit.md) echo "CloudKit Web Services, iCloud app data, ckAPIToken, ckWebAuthToken, ManagedCode.Storage.CloudKit, IStorage, .NET" ;;
82+
*) echo "ManagedCode.Storage, IStorage, .NET, storage" ;;
83+
esac
84+
}
85+
86+
keywords_for_api() {
87+
case "$1" in
88+
storage-server.md) echo "storage API, ASP.NET controllers, SignalR hub, upload, download, streaming, chunked upload, ranged download, ManagedCode.Storage.Server" ;;
89+
*) echo "ManagedCode.Storage API, HTTP, SignalR, ASP.NET, streaming" ;;
90+
esac
91+
}
92+
93+
keywords_for_adr() {
94+
case "$1" in
95+
0001-icloud-drive-support.md) echo "iCloud Drive, CloudKit, Apple, server-side storage, provider design, ManagedCode.Storage.CloudKit, ADR" ;;
96+
*) echo "architecture decision record, ADR, ManagedCode.Storage" ;;
97+
esac
98+
}
99+
100+
mkdir -p github-pages/features
101+
102+
WORDS=$(wc -w < README.md)
103+
MINUTES=$(( (WORDS + 200) / 200 ))
104+
105+
cat > github-pages/index.md << 'EOF'
106+
---
107+
layout: default
108+
title: Home
109+
description: ManagedCode.Storage documentation: cross-provider storage toolkit for .NET and ASP.NET streaming scenarios.
110+
keywords: ManagedCode.Storage, IStorage, .NET, ASP.NET, SignalR, Azure Blob Storage, Azure Data Lake, Amazon S3, Google Cloud Storage, OneDrive, Google Drive, Dropbox, CloudKit, SFTP, chunked uploads, streaming uploads
111+
is_home: true
112+
nav_order: 1
113+
---
114+
EOF
115+
sed -i 's/^ //' github-pages/index.md
116+
cat README.md >> github-pages/index.md
117+
echo "" >> github-pages/index.md
118+
echo "<p class=\"reading-time\">${MINUTES} min read</p>" >> github-pages/index.md
119+
120+
cat > github-pages/setup.md << 'EOF'
121+
---
122+
layout: default
123+
title: Setup
124+
description: How to clone, build, and run tests for ManagedCode.Storage.
125+
keywords: ManagedCode.Storage setup, .NET 10, dotnet restore, dotnet build, dotnet test, Docker, Testcontainers, Azurite, LocalStack, FakeGcsServer, SFTP
126+
nav_order: 2
127+
---
128+
EOF
129+
sed -i 's/^ //' github-pages/setup.md
130+
rewrite_md_links < docs/Development/setup.md >> github-pages/setup.md
131+
132+
cat > github-pages/credentials.md << 'EOF'
133+
---
134+
layout: default
135+
title: Credentials
136+
description: How to obtain credentials for OneDrive, Google Drive, Dropbox, and CloudKit.
137+
keywords: OneDrive credentials, Microsoft Graph auth, Entra ID, Google Drive OAuth, Drive API, service account, Dropbox OAuth2, refresh token, CloudKit ckAPIToken, ckWebAuthToken
138+
nav_order: 3
139+
---
140+
EOF
141+
sed -i 's/^ //' github-pages/credentials.md
142+
rewrite_md_links < docs/Development/credentials.md >> github-pages/credentials.md
143+
144+
cat > github-pages/testing.md << 'EOF'
145+
---
146+
layout: default
147+
title: Testing
148+
description: Test strategy and how to run the ManagedCode.Storage test suite.
149+
keywords: ManagedCode.Storage tests, xUnit, Shouldly, integration tests, Testcontainers, Azurite, LocalStack, FakeGcsServer, HttpMessageHandler fakes
150+
nav_order: 4
151+
---
152+
EOF
153+
sed -i 's/^ //' github-pages/testing.md
154+
rewrite_md_links < docs/Testing/strategy.md >> github-pages/testing.md
155+
156+
cat > github-pages/features/index.md << 'EOF'
157+
---
158+
layout: default
159+
title: Features
160+
description: Documentation for major modules and providers in ManagedCode.Storage.
161+
keywords: IStorage, providers, Azure Blob, AWS S3, Google Cloud Storage, OneDrive, Google Drive, Dropbox, CloudKit, FileSystem, SFTP, Virtual File System, ASP.NET Server, SignalR
162+
nav_order: 5
163+
---
164+
EOF
165+
sed -i 's/^ //' github-pages/features/index.md
166+
rewrite_md_links < docs/Features/index.md >> github-pages/features/index.md
167+
168+
for file in docs/Features/*.md; do
169+
base=$(basename "$file")
170+
if [ "$base" = "index.md" ]; then
171+
continue
172+
fi
173+
174+
title=$(head -n 1 "$file" | sed 's/^# //')
175+
title_escaped=$(printf '%s' "$title" | sed 's/"/\\"/g')
176+
177+
desc=$(extract_description < "$file" | tr -d '\r\n')
178+
desc=$(printf '%s' "$desc" | sed -E 's/[[:space:]]+/ /g; s/[[:space:]]+$//; s/:$//')
179+
if [ ${#desc} -gt 160 ]; then
180+
desc="${desc:0:159}…"
181+
fi
182+
if [ -z "${desc}" ]; then
183+
desc="${title} documentation."
184+
fi
185+
desc_escaped=$(printf '%s' "$desc" | sed 's/"/\\"/g')
186+
187+
keywords=$(keywords_for_feature "$base")
188+
keywords_escaped=$(printf '%s' "$keywords" | sed 's/"/\\"/g')
189+
cat > "github-pages/features/$base" << EOF
190+
---
191+
layout: default
192+
title: "${title_escaped}"
193+
description: "${desc_escaped}"
194+
keywords: "${keywords_escaped}"
195+
---
196+
EOF
197+
sed -i 's/^ //' "github-pages/features/$base"
198+
rewrite_md_links < "$file" >> "github-pages/features/$base"
199+
done
200+
201+
mkdir -p github-pages/adr
202+
203+
cat > github-pages/adr/index.md << 'EOF'
204+
---
205+
layout: default
206+
title: ADR
207+
description: Architecture Decision Records (ADR) for ManagedCode.Storage.
208+
keywords: architecture decisions, ADR, ManagedCode.Storage, design decisions, providers, CloudKit, iCloud Drive
209+
nav_order: 6
210+
---
211+
EOF
212+
sed -i 's/^ //' github-pages/adr/index.md
213+
rewrite_md_links < docs/ADR/index.md >> github-pages/adr/index.md
214+
215+
for file in docs/ADR/*.md; do
216+
base=$(basename "$file")
217+
if [ "$base" = "index.md" ]; then
218+
continue
219+
fi
220+
221+
title=$(head -n 1 "$file" | sed 's/^# //')
222+
title_escaped=$(printf '%s' "$title" | sed 's/"/\\"/g')
223+
224+
desc=$(extract_description < "$file" | tr -d '\r\n')
225+
desc=$(printf '%s' "$desc" | sed -E 's/[[:space:]]+/ /g; s/[[:space:]]+$//; s/:$//')
226+
if [ ${#desc} -gt 160 ]; then
227+
desc="${desc:0:159}…"
228+
fi
229+
if [ -z "${desc}" ]; then
230+
desc="${title} decision record."
231+
fi
232+
desc_escaped=$(printf '%s' "$desc" | sed 's/"/\\"/g')
233+
234+
keywords=$(keywords_for_adr "$base")
235+
keywords_escaped=$(printf '%s' "$keywords" | sed 's/"/\\"/g')
236+
cat > "github-pages/adr/$base" << EOF
237+
---
238+
layout: default
239+
title: "${title_escaped}"
240+
description: "${desc_escaped}"
241+
keywords: "${keywords_escaped}"
242+
---
243+
EOF
244+
sed -i 's/^ //' "github-pages/adr/$base"
245+
rewrite_md_links < "$file" >> "github-pages/adr/$base"
246+
done
247+
248+
mkdir -p github-pages/api
249+
250+
cat > github-pages/api/index.md << 'EOF'
251+
---
252+
layout: default
253+
title: API
254+
description: HTTP and SignalR API documentation for ManagedCode.Storage.Server.
255+
keywords: storage API, HTTP, SignalR, ASP.NET controllers, upload, download, streaming, chunked uploads, ranged downloads, ManagedCode.Storage.Server
256+
nav_order: 7
257+
---
258+
EOF
259+
sed -i 's/^ //' github-pages/api/index.md
260+
rewrite_md_links < docs/API/index.md >> github-pages/api/index.md
261+
262+
for file in docs/API/*.md; do
263+
base=$(basename "$file")
264+
if [ "$base" = "index.md" ]; then
265+
continue
266+
fi
267+
268+
title=$(head -n 1 "$file" | sed 's/^# //')
269+
title_escaped=$(printf '%s' "$title" | sed 's/"/\\"/g')
270+
271+
desc=$(extract_description < "$file" | tr -d '\r\n')
272+
desc=$(printf '%s' "$desc" | sed -E 's/[[:space:]]+/ /g; s/[[:space:]]+$//; s/:$//')
273+
if [ ${#desc} -gt 160 ]; then
274+
desc="${desc:0:159}…"
275+
fi
276+
if [ -z "${desc}" ]; then
277+
desc="${title} documentation."
278+
fi
279+
desc_escaped=$(printf '%s' "$desc" | sed 's/"/\\"/g')
280+
281+
keywords=$(keywords_for_api "$base")
282+
keywords_escaped=$(printf '%s' "$keywords" | sed 's/"/\\"/g')
283+
cat > "github-pages/api/$base" << EOF
284+
---
285+
layout: default
286+
title: "${title_escaped}"
287+
description: "${desc_escaped}"
288+
keywords: "${keywords_escaped}"
289+
---
290+
EOF
291+
sed -i 's/^ //' "github-pages/api/$base"
292+
rewrite_md_links < "$file" >> "github-pages/api/$base"
293+
done
294+
295+
cat > github-pages/templates.md << 'EOF'
296+
---
297+
layout: default
298+
title: Templates
299+
description: Documentation templates used in this repository (Feature and ADR templates).
300+
keywords: documentation templates, feature template, ADR template, MCAF, ManagedCode.Storage docs
301+
nav_order: 8
302+
---
303+
304+
# Templates
305+
306+
These templates are used to keep documentation consistent and MCAF-friendly.
307+
308+
<div class="templates-list">
309+
EOF
310+
sed -i 's/^ //' github-pages/templates.md
311+
312+
for file in docs/templates/*.md; do
313+
if [ -f "$file" ]; then
314+
filename=$(basename "$file")
315+
name="${filename%.md}"
316+
317+
echo "<div class=\"template-item\">" >> github-pages/templates.md
318+
echo "<span class=\"template-name\">${name}</span>" >> github-pages/templates.md
319+
echo "<div class=\"template-links\">" >> github-pages/templates.md
320+
echo "<a href=\"https://github.com/managedcode/Storage/blob/main/docs/templates/${filename}\">View</a>" >> github-pages/templates.md
321+
echo "<a href=\"https://raw.githubusercontent.com/managedcode/Storage/main/docs/templates/${filename}\" download>Download</a>" >> github-pages/templates.md
322+
echo "</div>" >> github-pages/templates.md
323+
echo "</div>" >> github-pages/templates.md
324+
fi
325+
done
326+
327+
echo "</div>" >> github-pages/templates.md
328+
329+
- name: Setup Pages
330+
uses: actions/configure-pages@v5
331+
332+
- name: Build with Jekyll
333+
uses: actions/jekyll-build-pages@v1
334+
with:
335+
source: ./github-pages
336+
destination: ./_site
337+
338+
- name: Upload artifact
339+
uses: actions/upload-pages-artifact@v3
340+
341+
deploy:
342+
needs: build
343+
runs-on: ubuntu-latest
344+
steps:
345+
- name: Deploy to GitHub Pages
346+
id: deployment
347+
uses: actions/deploy-pages@v4

0 commit comments

Comments
 (0)