Skip to content

Commit c8fed1d

Browse files
authored
Merge pull request #1 from Kapusch/phase2/ai-ready-baseline
Add Facebook Login interop with CI and sample project
2 parents 0c5d280 + d09c961 commit c8fed1d

36 files changed

Lines changed: 1588 additions & 1 deletion

.editorconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
trim_trailing_whitespace = true
8+
9+
[*.cs]
10+
indent_style = tab
11+
indent_size = 4
12+
13+
[*.{yml,yaml,json,md,sh}]
14+
indent_style = space
15+
indent_size = 2

.github/pull_request_template.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Summary
2+
3+
- What does this change do?
4+
5+
## Checklist
6+
7+
- [ ] No secrets committed
8+
- [ ] Built wrapper: `bash src/Kapusch.FacebookApisForiOSComponents/Native/iOS/build.sh`
9+
- [ ] Collected SDK xcframeworks: `bash src/Kapusch.FacebookApisForiOSComponents/Native/iOS/collect-facebook-xcframeworks.sh`
10+
- [ ] Packed NuGet: `dotnet pack src/Kapusch.FacebookApisForiOSComponents/Kapusch.FacebookApisForiOSComponents.csproj -c Release -o artifacts/nuget`
11+
- [ ] Updated docs if behavior/integration changed

.github/workflows/ci.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: ci
2+
3+
on:
4+
pull_request:
5+
workflow_dispatch:
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
build_pack_ios:
12+
runs-on: macos-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: actions/setup-dotnet@v4
17+
with:
18+
dotnet-version: "10.0.x"
19+
20+
- name: Install iOS workload
21+
run: |
22+
dotnet workload install ios
23+
24+
- name: Cache NuGet
25+
uses: actions/cache@v4
26+
with:
27+
path: ~/.nuget/packages
28+
key: ${{ runner.os }}-nuget-${{ hashFiles('global.json', '**/*.csproj') }}
29+
30+
- name: Cache SwiftPM scratch
31+
uses: actions/cache@v4
32+
with:
33+
path: |
34+
src/Kapusch.FacebookApisForiOSComponents/Native/iOS/build/spm
35+
key: ${{ runner.os }}-swiftpm-${{ hashFiles('src/Kapusch.FacebookApisForiOSComponents/Native/iOS/KapuschFacebookAuthInterop/Package.resolved') }}
36+
37+
- name: Build iOS wrapper
38+
run: |
39+
bash src/Kapusch.FacebookApisForiOSComponents/Native/iOS/build.sh
40+
41+
- name: Collect Facebook xcframeworks
42+
run: |
43+
bash src/Kapusch.FacebookApisForiOSComponents/Native/iOS/collect-facebook-xcframeworks.sh
44+
45+
- name: Pack
46+
run: |
47+
dotnet pack src/Kapusch.FacebookApisForiOSComponents/Kapusch.FacebookApisForiOSComponents.csproj \
48+
-c Release \
49+
-o artifacts/nuget
50+
51+
- name: Validate nupkg layout
52+
run: |
53+
python3 - <<'PY'
54+
import glob, sys, zipfile
55+
56+
nupkgs = glob.glob("artifacts/nuget/*.nupkg")
57+
if not nupkgs:
58+
print("ERROR: no .nupkg found under artifacts/nuget/")
59+
sys.exit(1)
60+
61+
nupkg = sorted(nupkgs)[-1]
62+
print(f"Validating {nupkg}")
63+
64+
z = zipfile.ZipFile(nupkg)
65+
names = set(z.namelist())
66+
67+
required = [
68+
"buildTransitive/Kapusch.Facebook.iOS.targets",
69+
"kfb.xcframework/Info.plist",
70+
"fb/FBAEMKit.xcframework/Info.plist",
71+
"fb/FBSDKCoreKit.xcframework/Info.plist",
72+
"fb/FBSDKCoreKit_Basics.xcframework/Info.plist",
73+
"fb/FBSDKGamingServicesKit.xcframework/Info.plist",
74+
"fb/FBSDKLoginKit.xcframework/Info.plist",
75+
"fb/FBSDKShareKit.xcframework/Info.plist",
76+
]
77+
78+
missing = [p for p in required if p not in names]
79+
if missing:
80+
print("ERROR: missing required paths in nupkg:")
81+
for p in missing:
82+
print(f" - {p}")
83+
sys.exit(1)
84+
85+
# Guardrail: ensure the wrapper is not flattened at the package root.
86+
if "Info.plist" in names:
87+
print("ERROR: wrapper appears flattened (found 'Info.plist' at package root).")
88+
sys.exit(1)
89+
90+
print("OK: nupkg layout looks correct.")
91+
PY
92+
93+
- uses: actions/upload-artifact@v4
94+
with:
95+
name: nuget
96+
path: artifacts/nuget/*.nupkg

.github/workflows/publish.yml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
name: publish
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
tags:
7+
- "v*"
8+
9+
permissions:
10+
contents: read
11+
packages: write
12+
13+
jobs:
14+
pack_and_publish:
15+
runs-on: macos-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0
20+
21+
- name: Determine package version
22+
id: version
23+
shell: bash
24+
run: |
25+
if [[ "${{ github.ref }}" =~ ^refs/tags/v ]]; then
26+
REF="${{ github.ref }}"
27+
VERSION="${REF#refs/tags/v}"
28+
else
29+
CSPROJ="src/Kapusch.FacebookApisForiOSComponents/Kapusch.FacebookApisForiOSComponents.csproj"
30+
BASE_VERSION=$(grep -oE '<Version>[^<]+' "$CSPROJ" | head -n 1 | sed 's/<Version>//' || echo "0.1.0")
31+
COMMIT_SHORT=$(git rev-parse --short HEAD)
32+
RUN_NUMBER="${{ github.run_number }}"
33+
VERSION="${BASE_VERSION}-prerelease.${RUN_NUMBER}.${COMMIT_SHORT}"
34+
fi
35+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
36+
echo "Package version: ${VERSION}"
37+
38+
- uses: actions/setup-dotnet@v4
39+
with:
40+
dotnet-version: "10.0.x"
41+
42+
- name: Install iOS workload
43+
run: |
44+
dotnet workload install ios
45+
46+
- name: Cache NuGet
47+
uses: actions/cache@v4
48+
with:
49+
path: ~/.nuget/packages
50+
key: ${{ runner.os }}-nuget-${{ hashFiles('global.json', '**/*.csproj') }}
51+
52+
- name: Cache SwiftPM scratch
53+
uses: actions/cache@v4
54+
with:
55+
path: |
56+
src/Kapusch.FacebookApisForiOSComponents/Native/iOS/build/spm
57+
key: ${{ runner.os }}-swiftpm-${{ hashFiles('src/Kapusch.FacebookApisForiOSComponents/Native/iOS/KapuschFacebookAuthInterop/Package.resolved') }}
58+
59+
- name: Build iOS wrapper
60+
run: |
61+
bash src/Kapusch.FacebookApisForiOSComponents/Native/iOS/build.sh
62+
63+
- name: Collect Facebook xcframeworks
64+
run: |
65+
bash src/Kapusch.FacebookApisForiOSComponents/Native/iOS/collect-facebook-xcframeworks.sh
66+
67+
- name: Pack
68+
run: |
69+
dotnet pack src/Kapusch.FacebookApisForiOSComponents/Kapusch.FacebookApisForiOSComponents.csproj \
70+
-c Release \
71+
-o artifacts/nuget \
72+
/p:PackageVersion="${{ steps.version.outputs.version }}"
73+
74+
- name: Validate nupkg layout
75+
run: |
76+
python3 - <<'PY'
77+
import glob, sys, zipfile
78+
79+
nupkgs = glob.glob("artifacts/nuget/*.nupkg")
80+
if not nupkgs:
81+
print("ERROR: no .nupkg found under artifacts/nuget/")
82+
sys.exit(1)
83+
84+
nupkg = sorted(nupkgs)[-1]
85+
print(f"Validating {nupkg}")
86+
87+
z = zipfile.ZipFile(nupkg)
88+
names = set(z.namelist())
89+
90+
required = [
91+
"buildTransitive/Kapusch.Facebook.iOS.targets",
92+
"kfb.xcframework/Info.plist",
93+
"fb/FBAEMKit.xcframework/Info.plist",
94+
"fb/FBSDKCoreKit.xcframework/Info.plist",
95+
"fb/FBSDKCoreKit_Basics.xcframework/Info.plist",
96+
"fb/FBSDKGamingServicesKit.xcframework/Info.plist",
97+
"fb/FBSDKLoginKit.xcframework/Info.plist",
98+
"fb/FBSDKShareKit.xcframework/Info.plist",
99+
]
100+
101+
missing = [p for p in required if p not in names]
102+
if missing:
103+
print("ERROR: missing required paths in nupkg:")
104+
for p in missing:
105+
print(f" - {p}")
106+
sys.exit(1)
107+
108+
if "Info.plist" in names:
109+
print("ERROR: wrapper appears flattened (found 'Info.plist' at package root).")
110+
sys.exit(1)
111+
112+
print("OK: nupkg layout looks correct.")
113+
PY
114+
115+
- name: Push to GitHub Packages
116+
env:
117+
NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
118+
run: |
119+
dotnet nuget push artifacts/nuget/*.nupkg \
120+
--api-key "$NUGET_AUTH_TOKEN" \
121+
--source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" \
122+
--skip-duplicate

.github/workflows/sample-ios.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: sample-ios (manual)
2+
3+
on:
4+
workflow_dispatch:
5+
6+
permissions:
7+
contents: read
8+
9+
jobs:
10+
build_sample_ios:
11+
runs-on: macos-15
12+
env:
13+
DOTNET_MULTILEVEL_LOOKUP: 0
14+
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
15+
DOTNET_CLI_TELEMETRY_OPTOUT: 1
16+
DOTNET_NOLOGO: true
17+
DOTNET_CLI_WORKLOAD_UPDATE_NOTIFICATION_LEVEL: Disable
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Setup Xcode 26.0
23+
uses: maxim-lobanov/setup-xcode@v1
24+
with:
25+
xcode-version: "26.0"
26+
27+
- uses: actions/setup-dotnet@v4
28+
with:
29+
dotnet-version: "10.0.x"
30+
31+
- name: Pin workload update mode (manifests)
32+
shell: bash
33+
run: |
34+
dotnet workload config --update-mode manifests
35+
dotnet workload config --update-mode
36+
37+
- name: Purge incompatible iOS packs (cache defense)
38+
shell: bash
39+
run: |
40+
set -euo pipefail
41+
PACKS_DIR="$HOME/.dotnet/packs"
42+
for v in 26.2; do
43+
if [ -d "$PACKS_DIR" ] && compgen -G "$PACKS_DIR/Microsoft.iOS.*_${v}*" > /dev/null; then
44+
echo "Removing cached iOS ${v} packs from $PACKS_DIR"
45+
rm -rf "$PACKS_DIR"/Microsoft.iOS.*_${v}*
46+
fi
47+
done
48+
49+
- name: Install iOS workload
50+
shell: bash
51+
run: |
52+
dotnet workload install ios --skip-manifest-update
53+
54+
- name: Diagnostics (.NET + workloads)
55+
shell: bash
56+
run: |
57+
dotnet --info
58+
dotnet workload list
59+
60+
- name: Build iOS wrapper
61+
run: |
62+
bash src/Kapusch.FacebookApisForiOSComponents/Native/iOS/build.sh
63+
64+
- name: Collect Facebook xcframeworks
65+
run: |
66+
bash src/Kapusch.FacebookApisForiOSComponents/Native/iOS/collect-facebook-xcframeworks.sh
67+
68+
- name: Build iOS sample (simulator, no signing)
69+
run: |
70+
dotnet build samples/Kapusch.Facebook.iOS.Sample/Kapusch.Facebook.iOS.Sample.csproj \
71+
-c Debug \
72+
-p:RuntimeIdentifier=iossimulator-arm64 \
73+
-p:EnableCodeSigning=false
74+

.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# .NET
2+
bin/
3+
obj/
4+
*.user
5+
*.suo
6+
*.userosscache
7+
*.sln.docstates
8+
9+
# NuGet
10+
*.nupkg
11+
*.snupkg
12+
artifacts/
13+
14+
# macOS
15+
.DS_Store
16+
17+
# SwiftPM / Xcode
18+
.build/
19+
*.xcworkspace/
20+
DerivedData/
21+
22+
# Local caches used by buildTransitive restore
23+
.kapusch/
24+
25+
# Native build output (repo-only)
26+
src/**/Native/iOS/build/
27+
28+
# Sample local config
29+
samples/**/Info.plist
30+
samples/**/GoogleService-Info.plist
31+
samples/**/secrets.*

AGENTS.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Kapusch.FacebookApisForiOSComponents — AI Working Agreement
2+
3+
## Goals
4+
- Produce a reproducible iOS NuGet package for Facebook Login interop.
5+
- Do not commit secrets.
6+
7+
## Packaging constraints
8+
- Public OSS repo: keep docs/sample generic and not app-specific.
9+
- The NuGet ships the required `xcframework`s and references them via `NativeReference`.
10+
- Consuming apps must not download native deps at build time.
11+
- The repo may use SwiftPM during CI/build to fetch the upstream Facebook iOS SDK, but consuming apps must not download native deps at build time.
12+
13+
## Repo layout
14+
- `src/Kapusch.FacebookApisForiOSComponents/` — NuGet project (managed API + buildTransitive MSBuild)
15+
- `src/Kapusch.FacebookApisForiOSComponents/Native/iOS/` — Swift wrapper source + scripts (repo-only)
16+
- `Docs/` — integration docs
17+
- `samples/` — optional sample template (no secrets committed)
18+
19+
## Safety
20+
- Do not add new dependency ingestion paths without documenting them in `README.md`.
21+
- Do not commit real app ids/secrets.

0 commit comments

Comments
 (0)