Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions .asc/workflow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
{
"env": {
"ASC_PROFILE": "Runline",
"APP_ID": "6766299514",
"BUNDLE_ID": "com.matthewparris.runline",
"VERSION": "1.0",
"PROJECT": "CursorMobile.xcodeproj",
"SCHEME": "CursorMobile",
"SIM_DESTINATION": "platform=iOS Simulator,name=iPhone 17,OS=26.4.1",
"TESTFLIGHT_GROUP_ID": "9ddf92fa-5b17-48ca-9833-5d83c3e31d3d",
"INTERNAL_TESTFLIGHT_GROUP_ID": "a252108c-c4bc-4b6b-94cd-519b7be04c68",
"LOCALE": "en-US",
"TEST_NOTES": "Verify Cloud Agent and Cursor SDK workflows, iPhone and iPad layouts, chat composer, attachments, model and MCP controls, Settings, light mode, and dark mode."
},
"before_all": "asc --profile $ASC_PROFILE auth status --validate --output json >/dev/null",
"after_all": "echo workflow_done >&2",
"error": "echo workflow_failed >&2",
"workflows": {
"asc-health": {
"description": "Verify ASC auth, app resolution, TestFlight groups, and the latest visible builds.",
"steps": [
{
"name": "auth_status",
"run": "asc --profile $ASC_PROFILE auth status --validate --verbose"
},
{
"name": "app",
"run": "asc --profile $ASC_PROFILE apps view --id $APP_ID --output json"
},
{
"name": "groups",
"run": "asc --profile $ASC_PROFILE testflight groups list --app $APP_ID --output json"
},
{
"name": "builds",
"run": "asc --profile $ASC_PROFILE builds list --app $APP_ID --version $VERSION --platform IOS --limit 10 --sort -uploadedDate --output json"
}
]
},
"preflight": {
"description": "Run local checks before archiving a TestFlight build.",
"steps": [
{
"name": "repo_clean",
"run": "test -z \"$(git status --short)\" || { git status --short >&2; echo 'Working tree must be clean before release.' >&2; exit 1; }"
},
{
"name": "diff_check",
"run": "git diff --check"
},
{
"name": "orchestrator_typecheck",
"run": "npm --prefix orchestrator run typecheck"
},
{
"name": "ios_tests",
"run": "xcodebuild test -project $PROJECT -scheme $SCHEME -destination \"$SIM_DESTINATION\""
}
]
},
"testflight": {
"description": "Set an explicit build number, run checks, archive, upload, add What to Test notes, and distribute to TestFlight.",
"env": {
"BUILD_NUMBER": ""
},
"steps": [
{
"name": "require_build_number",
"run": "test -n \"$BUILD_NUMBER\" || { echo 'Pass BUILD_NUMBER, for example: asc workflow run testflight BUILD_NUMBER:9' >&2; exit 2; }"
},
{
"workflow": "preflight"
},
{
"name": "set_build_number",
"run": "ruby Tools/set_build_number.rb \"$BUILD_NUMBER\""
},
{
"name": "generate_project",
"run": "xcodegen generate"
},
{
"name": "archive",
"run": "asc --profile $ASC_PROFILE xcode archive --project $PROJECT --scheme $SCHEME --configuration Release --clean --overwrite --archive-path \".asc/artifacts/Runline-${VERSION}-${BUILD_NUMBER}.xcarchive\" --xcodebuild-flag=-destination --xcodebuild-flag=generic/platform=iOS --xcodebuild-flag=-allowProvisioningUpdates --output json"
},
{
"name": "upload",
"run": "asc --profile $ASC_PROFILE xcode export --archive-path \".asc/artifacts/Runline-${VERSION}-${BUILD_NUMBER}.xcarchive\" --export-options ExportOptions-TestFlightUpload.plist --ipa-path \".asc/artifacts/Runline-${VERSION}-${BUILD_NUMBER}.ipa\" --overwrite --wait --xcodebuild-flag=-allowProvisioningUpdates --output json"
},
{
"name": "resolve_uploaded_build",
"run": "asc --profile $ASC_PROFILE builds info --app $APP_ID --build-number \"$BUILD_NUMBER\" --version \"$VERSION\" --platform IOS --output json",
"outputs": {
"BUILD_ID": "$.data.id"
}
},
{
"name": "test_notes",
"run": "if [ -n \"$TEST_NOTES\" ]; then asc --profile $ASC_PROFILE builds test-notes create --build-id \"${steps.resolve_uploaded_build.BUILD_ID}\" --locale \"$LOCALE\" --whats-new \"$TEST_NOTES\" || asc --profile $ASC_PROFILE builds test-notes update --build-id \"${steps.resolve_uploaded_build.BUILD_ID}\" --locale \"$LOCALE\" --whats-new \"$TEST_NOTES\"; else echo 'Skipping TestFlight notes because TEST_NOTES is empty.' >&2; fi"
},
{
"name": "distribute",
"run": "if [ -n \"$TESTFLIGHT_GROUP_ID\" ]; then asc --profile $ASC_PROFILE builds add-groups --build-id \"${steps.resolve_uploaded_build.BUILD_ID}\" --group \"$TESTFLIGHT_GROUP_ID\"; else echo 'Skipping TestFlight group distribution because TESTFLIGHT_GROUP_ID is empty.' >&2; fi"
},
{
"name": "summary",
"run": "asc --profile $ASC_PROFILE builds info --build-id \"${steps.resolve_uploaded_build.BUILD_ID}\" --output json"
}
]
},
"distribute-existing": {
"description": "Attach notes and distribute an already uploaded build by BUILD_ID or BUILD_NUMBER.",
"env": {
"BUILD_ID": "",
"BUILD_NUMBER": ""
},
"steps": [
{
"name": "require_build",
"run": "test -n \"$BUILD_ID\" -o -n \"$BUILD_NUMBER\" || { echo 'Pass BUILD_ID or BUILD_NUMBER, for example: asc workflow run distribute-existing BUILD_NUMBER:8' >&2; exit 2; }"
},
{
"name": "resolve_existing_build",
"run": "if [ -n \"$BUILD_ID\" ]; then asc --profile $ASC_PROFILE builds info --build-id \"$BUILD_ID\" --output json; else asc --profile $ASC_PROFILE builds info --app $APP_ID --build-number \"$BUILD_NUMBER\" --version \"$VERSION\" --platform IOS --output json; fi",
"outputs": {
"BUILD_ID": "$.data.id"
}
},
{
"name": "test_notes",
"run": "if [ -n \"$TEST_NOTES\" ]; then asc --profile $ASC_PROFILE builds test-notes create --build-id \"${steps.resolve_existing_build.BUILD_ID}\" --locale \"$LOCALE\" --whats-new \"$TEST_NOTES\" || asc --profile $ASC_PROFILE builds test-notes update --build-id \"${steps.resolve_existing_build.BUILD_ID}\" --locale \"$LOCALE\" --whats-new \"$TEST_NOTES\"; else echo 'Skipping TestFlight notes because TEST_NOTES is empty.' >&2; fi"
},
{
"name": "distribute",
"run": "if [ -n \"$TESTFLIGHT_GROUP_ID\" ]; then asc --profile $ASC_PROFILE builds add-groups --build-id \"${steps.resolve_existing_build.BUILD_ID}\" --group \"$TESTFLIGHT_GROUP_ID\"; else echo 'Skipping TestFlight group distribution because TESTFLIGHT_GROUP_ID is empty.' >&2; fi"
},
{
"name": "summary",
"run": "asc --profile $ASC_PROFILE builds info --build-id \"${steps.resolve_existing_build.BUILD_ID}\" --output json"
}
]
}
}
}
54 changes: 54 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Bug report
description: Report a reproducible Runline issue.
title: "[Bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Do not include Cursor API keys, bridge pairing tokens, Apple credentials, private repository contents, or other secrets.
- type: input
id: version
attributes:
label: App or bridge version
description: Include the TestFlight build number or `runline-bridge --version`.
placeholder: "Runline 1.0 (11), runline-bridge 0.1.0"
validations:
required: true
- type: dropdown
id: mode
attributes:
label: Mode
options:
- Cloud Agent
- Cursor SDK with Runline Bridge
- Settings or onboarding
- Other
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
placeholder: "1. Open...\n2. Tap...\n3. See..."
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual behavior
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment
placeholder: "iPhone/iPad model, iOS version, Mac version, Node version, network setup"
validations:
required: false
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security report
url: mailto:parrisdigital@gmail.com
about: Please report security vulnerabilities privately.
33 changes: 33 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Feature request
description: Suggest a focused improvement.
title: "[Feature]: "
labels: ["enhancement"]
body:
- type: textarea
id: problem
attributes:
label: Problem
description: What user workflow should this improve?
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposal
description: What should Runline do?
validations:
required: true
- type: dropdown
id: area
attributes:
label: Area
options:
- Cloud Agent
- Cursor SDK and Runline Bridge
- iPhone UI
- iPad UI
- Notifications
- Documentation
- Other
validations:
required: true
16 changes: 16 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Summary

-

## Testing

- [ ] `npm --prefix orchestrator run typecheck`
- [ ] `npm --prefix orchestrator run build`
- [ ] iOS tests or manual simulator testing, as relevant

## Checklist

- [ ] Cloud Agent mode still works without Runline Bridge
- [ ] Cursor SDK mode remains optional and clearly labeled
- [ ] No secrets, signing files, generated archives, IPAs, or local artifacts are committed
- [ ] Documentation was updated if behavior changed
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: npm
directory: /orchestrator
schedule:
interval: weekly
open-pull-requests-limit: 5
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI

on:
pull_request:
push:
branches:
- main

permissions:
contents: read

jobs:
bridge:
name: Runline Bridge
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v6
with:
node-version: 20
cache: npm
cache-dependency-path: orchestrator/npm-shrinkwrap.json
- run: npm ci
working-directory: orchestrator
- run: npm run typecheck
working-directory: orchestrator
- run: npm run build
working-directory: orchestrator
- run: npm pack --pack-destination /tmp
working-directory: orchestrator

project-metadata:
name: Project Metadata
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- run: xcodebuild -list -project CursorMobile.xcodeproj
- run: ruby -c Tools/set_build_number.rb
- run: plutil -lint ExportOptions-AppStore.plist ExportOptions-TestFlightUpload.plist CursorMobile/Resources/Info.plist CursorMobile/Resources/PrivacyInfo.xcprivacy CursorMobile/Resources/CursorMobile.entitlements
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,23 @@ Package.resolved
# Node
node_modules/
**/node_modules/
orchestrator/dist/

# Local secrets and generated config
.asc/artifacts/
.asc/runs/
.env
.env.*
.npmrc
*.local.xcconfig
Secrets.plist
*.p8
*.p12
*.pem
*.key
*.cer
*.mobileprovision
*.provisionprofile

# macOS
.DS_Store
Expand Down
6 changes: 6 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[allowlist]
description = "Allow documentation placeholders that are intentionally non-secret."
regexes = [
'''YOUR_CURSOR_API_KEY''',
'''your-cursor-key'''
]
23 changes: 23 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Code of Conduct

## Our Pledge

We pledge to make participation in this project respectful and harassment-free for everyone.

## Expected Behavior

- Be direct, constructive, and respectful.
- Assume good intent while asking for clarification when needed.
- Keep technical criticism focused on the work.
- Respect privacy and do not post secrets, tokens, private keys, private repository contents, or personal data.

## Unacceptable Behavior

- Harassment, insults, threats, or discriminatory language.
- Publishing private information without permission.
- Publicly disclosing security vulnerabilities before maintainers have had a reasonable chance to respond.
- Repeatedly derailing issues or pull requests.

## Enforcement

Report concerns to `parrisdigital@gmail.com`. Maintainers may remove comments, close issues, reject pull requests, or block participants when needed to protect the project.
Loading
Loading