Thank you for your interest in contributing to the Adaptive Cards Mobile SDK! This document provides guidelines and instructions for contributing.
- Code of Conduct
- Getting Started
- Development Setup
- Cross-Platform Parity Requirements
- Making Changes
- Testing
- Submitting Changes
- Style Guidelines
- Documentation
This project follows the Microsoft Open Source Code of Conduct. Be respectful and inclusive in all interactions.
For iOS Development:
- macOS 13.0 or later
- Xcode 15.0 or later
- Swift 5.9 or later
- Swift Package Manager (primary), CocoaPods optional
- Git
For Android Development:
- Android Studio Hedgehog (2023.1.1) or later
- JDK 17 or later
- Kotlin 1.9 or later
- Android SDK 26+ (Oreo)
- Git
- Check the issue tracker
- Look for issues labeled
good first issuefor beginner-friendly tasks - Issues labeled
help wantedare great for contributors - Comment on an issue to indicate you're working on it
-
Clone the repository:
git clone https://github.com/VikrantSingh01/AdaptiveCards-Mobile.git cd AdaptiveCards-Mobile/ios -
Open in Xcode:
open Package.swift
-
Build the project:
swift build
-
Run tests:
swift test
-
Clone the repository:
git clone https://github.com/VikrantSingh01/AdaptiveCards-Mobile.git cd AdaptiveCards-Mobile/android -
Open in Android Studio:
- Open Android Studio
- Select "Open an Existing Project"
- Navigate to
android/directory
-
Build the project:
./gradlew build
-
Run tests:
./gradlew test
The Adaptive Cards Mobile SDK maintains strict cross-platform parity. All features must work identically on both iOS and Android. Both sample apps support identical adaptivecards:// deep link routes for automated testing and demo scripts.
-
Simultaneous Implementation: New elements, actions, or features must be implemented on both platforms in the same PR or coordinated PRs.
-
Schema Compliance: All changes must comply with Adaptive Cards v1.6 specification. See
docs/architecture/PARITY_TARGET.mdfor details. -
Shared Test Cards: Use test cards from
shared/test-cards/to ensure consistent testing across platforms. -
Documentation: Update
docs/architecture/PARITY_MATRIX.mdto track implementation status.
When adding a new card element or action:
-
iOS Implementation:
- Add model to
ios/Sources/ACCore/Models/ - Add view to
ios/Sources/ACRendering/Views/ - Update
SchemaValidator.swiftto include new type - Add tests to
ios/Tests/
- Add model to
-
Android Implementation:
- Add model to
android/ac-core/src/main/kotlin/.../models/ - Add composable to
android/ac-rendering/src/main/kotlin/.../composables/ - Update
SchemaValidator.ktto include new type - Add tests to
android/ac-core/src/test/andandroid/ac-rendering/src/test/
- Add model to
-
Shared Test Card:
- Create JSON test card in
shared/test-cards/ - Validate with
shared/scripts/validate-test-cards.sh
- Create JSON test card in
-
Schema Update:
- Update
shared/schema/adaptive-card-schema-1.6.json(if v1.6 feature) - Add round-trip serialization tests on both platforms
- Update
-
Documentation:
- Update
docs/architecture/PARITY_MATRIX.md - Update
shared/RENDERING_PARITY_CHECKLIST.md - Add implementation notes
- Update
Before submitting a PR:
# Run schema coverage comparison
bash shared/scripts/compare-schema-coverage.sh
# This script checks:
# - Element types match between iOS and Android
# - Action types match between iOS and Android
# - No significant parity gaps (difference > 2)The CI pipeline includes a parity gate that:
- Runs iOS tests
- Runs Android tests
- Validates test cards against v1.6 schema
- Compares schema coverage between platforms
- Fails if either platform fails or significant gaps exist
See .github/workflows/parity-gate.yml for details.
In rare cases, platform-specific limitations may prevent exact parity:
- Document in
docs/architecture/PARITY_MATRIX.md - Add tests that demonstrate the limitation
- Mark status as
⚠️ Partial with notes
main- Stable release and active development branchfeature/*- New feature branchesbugfix/*- Bug fix brancheshotfix/*- Critical production fixes
git checkout main
git pull origin main
git checkout -b feature/your-feature-nameFollow the Conventional Commits specification:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat- New featurefix- Bug fixdocs- Documentation changesstyle- Code style changes (formatting, etc.)refactor- Code refactoringperf- Performance improvementstest- Test additions or changeschore- Build process or auxiliary tool changes
Examples:
feat(ios): add carousel element support
Implement carousel container with swipe gestures and
pagination indicators for iOS platform.
Closes #123
fix(android): resolve memory leak in card rendering
Fixed memory leak caused by retained references in
CompositionLocal providers.
Fixes #456
Run all tests:
cd ios
swift testRun specific test:
swift test --filter ACCoreTestsRun with coverage:
swift test --enable-code-coverageRun performance tests:
swift test --filter PerformanceTestsRun all tests:
cd android
./gradlew testRun specific module tests:
./gradlew :ac-core:testRun with coverage:
./gradlew testDebugUnitTestCoverage- All new features must include unit tests
- Bug fixes should include regression tests
- Aim for >80% code coverage
- All tests must pass before submitting PR
-
Update your branch:
git checkout main git pull origin main git checkout your-branch git rebase main
-
Push your changes:
git push origin your-branch
-
Create Pull Request:
- Go to GitHub repository
- Click "New Pull Request"
- Select
mainas base branch - Fill out PR template completely
-
Cross-Platform Parity (for schema/rendering changes):
- Changes implemented on both iOS and Android
- Tests added for both platforms
- SchemaValidator updated on both platforms (if new elements/actions)
- PARITY_MATRIX.md updated to reflect current status
- Shared test card added/updated in
shared/test-cards/(if applicable)
-
Code Quality:
- All tests pass (iOS:
swift test, Android:./gradlew test) - Code follows style guidelines (see below)
- No compiler warnings
- Code review feedback addressed
- All tests pass (iOS:
-
Documentation:
- Documentation is updated
- CHANGELOG.md is updated (for significant changes)
- Code comments added for complex logic
-
CI Checks:
- Parity gate passes (both iOS and Android tests)
- Lint checks pass
- No merge conflicts
-
Schema Compliance (if adding new elements/actions):
- Complies with Adaptive Cards v1.6 specification
- Schema file updated (
shared/schema/adaptive-card-schema-1.6.json) - Round-trip serialization tests pass
- Unknown elements handled gracefully
-
Optional but Recommended:
- Signed commits
- Performance tested with large cards
- Accessibility verified (VoiceOver/TalkBack)
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Unit tests added/updated
- [ ] Manual testing completed
- [ ] Tested on iOS 16+
- [ ] Tested on Android API 26+
## Screenshots (if applicable)
Add screenshots of UI changes
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No new warnings
- [ ] Tests pass locallyFollow Swift API Design Guidelines:
// Good
func parseCard(from json: String) throws -> AdaptiveCard {
guard let data = json.data(using: .utf8) else {
throw ParsingError.invalidJSON
}
return try JSONDecoder().decode(AdaptiveCard.self, from: data)
}
// Bad
func ParseCard(json: String) -> AdaptiveCard? {
let data = json.data(using: .utf8)
return try? JSONDecoder().decode(AdaptiveCard.self, from: data!)
}Key Points:
- Use descriptive names
- Prefer clarity over brevity
- Use
guardfor early exits - Handle errors explicitly
- Document public APIs with
///
Follow Kotlin Coding Conventions:
// Good
fun parseCard(json: String): Result<AdaptiveCard> {
return runCatching {
Json.decodeFromString<AdaptiveCard>(json)
}
}
// Bad
fun parseCard(json: String): AdaptiveCard? {
return try {
Json.decodeFromString<AdaptiveCard>(json)
} catch (e: Exception) {
null
}
}Key Points:
- Use meaningful names
- Prefer immutability (
valovervar) - Use
Resultfor error handling - Leverage Kotlin idioms
- Document public APIs with KDoc
iOS: Use SwiftLint
cd ios
swiftlint lint
swiftlint autocorrectAndroid: Use ktlint
cd android
./gradlew ktlintFormatiOS (Swift):
/// Parses an Adaptive Card from JSON string.
///
/// - Parameter json: The JSON string representing the card
/// - Returns: A parsed `AdaptiveCard` instance
/// - Throws: `ParsingError` if JSON is invalid
public func parseCard(from json: String) throws -> AdaptiveCard {
// Implementation
}Android (Kotlin):
/**
* Parses an Adaptive Card from JSON string.
*
* @param json The JSON string representing the card
* @return A parsed AdaptiveCard instance
* @throws JsonException if JSON is invalid
*/
fun parseCard(json: String): AdaptiveCard {
// Implementation
}- Update relevant README files
- Add examples for new features
- Update architecture docs if structure changes
- Keep documentation in sync with code
ios/
├── Package.swift # SPM manifest
├── Sources/
│ ├── ACCore/ # Core models
│ ├── ACRendering/ # SwiftUI rendering
│ ├── ACInputs/ # Input elements
│ └── ...
├── Tests/
│ ├── ACCoreTests/ # Unit tests
│ └── ...
└── README.md
android/
├── settings.gradle.kts # Module configuration
├── ac-core/ # Core models
├── ac-rendering/ # Compose rendering
├── ac-inputs/ # Input elements
└── ...
- Update version in
Package.swift(iOS) andgradle.properties(Android) - Update
CHANGELOG.md - Create release branch:
release/v1.x.x - Run full test suite
- Create and push tag:
git tag v1.x.x - GitHub Actions will build and publish artifacts
- Questions: Open a Discussion
- Bugs: Open an Issue
- Security: See SECURITY.md
Contributors will be acknowledged in:
- Release notes
- CHANGELOG.md
- GitHub contributors page
Thank you for contributing!