Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TRCL-2984 : Create 3P Suggested Release Instructions doc #23

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
18 changes: 17 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,20 @@ dydx/Pods/abacus/build
dydxV4/dydxV4/_Configurations/credentials.json
dydxV4/dydxV4/_Configurations/GoogleService-Info-Staging.plist
dydxV4/dydxV4/_Configurations/GoogleService-Info.plist
scripts/secrets
scripts/secrets

# fastlane specific
**/fastlane/report.xml

# deliver temporary files
**/fastlane/Preview.html

# scan temporary files
**/fastlane/test_output

*.p12
*.certSigningRequest
*.cer
*.mobileprovision
*.ipa
*.dSYM.*
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Other dependencies are specified by the Cocoapods and Swift Package Manager conf

# API Keys & Secrets
Unzip the `secrets.zip` from the `iOS Secrets` vault in the dYdX 1Password account. Ask a team member for access.
Add the `secrets/` folder to the native-ios-v4/scripts folder.
Add the `secrets/` folder to the v4-native-ios/scripts folder.

> `mv {REPLACE_WITH_PATH_TO_UNZIPPED}/secrets {REPLACE_WITH_REPO}/scripts`

Expand All @@ -45,7 +45,7 @@ Javascript code is generated in v4-client. To update

Get the desired commit from v4-client
Copy from {v4-client}/__native__/__ios__/v4-native-client.js
to {native-ios-v4}/dydx/dydxPresenters/_Feature/
to {v4-native-ios}/dydx/dydxPresenters/_Feature/

To generate v4-native-client.js from the v4-client repo, run

Expand Down
124 changes: 124 additions & 0 deletions docs/branching_strategy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Project Branching and Hotfix Strategy Guide

This document outlines the branching strategy our project adopts, accommodating regular development, releases, and hotfixes. Following this strategy ensures an organized development process and stable production code.

## 1. General Branching Strategy

Our branching method involves several branches serving distinct roles in the code changes' lifecycle. Here's what our branch structure looks like:

### 1.1 `main` Branch

- Stores official release history.
- Every commit represents a production-ready state.

### 1.2 `develop` Branch

- Serves as a pre-production staging area.
- It's where code merges before it's ready for production.

### 1.3 Feature Branches

- Branch off from `develop` and integrate back into it when the feature is complete.
- Used for single feature development or improvements.

### 1.4 Release Branches

- Branch off from `develop` when it reaches a production-ready state.
- These branches are long-lived and serve for creating a release history, enabling referencing or hotfixing in the future.

**Workflow Summary:**

1. Regular work (features and non-critical fixes) is done in feature branches.
2. These are merged into `develop` upon completion.
3. When `develop` is ready for production, a new `release/...` branch is created.
4. Release branches may receive minor polishing and bug fixing.
5. When finalized, the `release` branch merges into `main` and is tagged with a version number if commits were made in step 4. The release branch also merges back any changes into `develop`.

## 2. Hotfix Strategy

Hotfixes address critical production issues, requiring immediate resolution outside the regular cycle.

### 2.1 Hotfix Branches

- These are created from the appropriate `release/...` branch, providing a controlled area to fix the issue.
- These are no different than a normal release branch aside from being based on a previous `release/...` branch instead of `main`
- After testing, hotfixes merge into both `main` and `develop` to update the production version and include fixes in the upcoming releases.

**Hotfix Workflow:**

Let's say that an issue needing a hotfix was discovered in released version `1.0.1`

1. Locate the `release/1.0.1` branch.
2. Branch off into a new hotfix `release/1.0.2` branch.
```sh
git checkout release/1.0.1
git pull
git checkout -b release/1.0.2
```
3. Implement and test the fix rigorously on the hotfix branch.
4. Merge the hotfix branch into `main` and deploy to production.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the hotfix merged into 'main' can be confusing. For instance, if 'main' already contains the changes for version "1.1", and when a hotfix 1.0.2 is merged into 'main', it would be tagged after '1.1'.

I think it's better to just merging to 'develop' and let 'main' as-is. The change in the hotfix will be merged to 'main' when 'develop' gets merged to 'main' at some point in the future (i.e., when the next release happens).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what your saying, but I am curious if that is actually a reachable scenario.

If main already has 1.1 tag merged in, then we should have a release/1.1 branch and the hotfix release branch should then be release/1.1.1 if the hotfix is coming after the 1.1 changes were merged in.

In the other case, if we begin the hotfix work before 1.1 is released, then the 1.1 release should be paused until after the 1.0.2 hotfix is merged into develop & main

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah.. I think there could be scenarios where we need to support multiple releases. Some deployer might want to stay with 1.0 but ask us to fix some issue on 1.0, and meanwhile we have already moved on to 1.1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My feeling is that if a deployer wants to persist an older version, they should cherry pick hotfix commits, or modify their own fork with the hot fix changes. Otherwise, we must apply all hotfixes in a backwards way and I think that would be a large drain on resources. If anything, we should encourage users of our code to stay up-to-date rather than support out-of-date versions.

Consider this example: if we're on version 5.0.0, but we realize that 1.0.0 has a issue we want to fix, that means all version between 5.0.0 and 1.0.0 need to have the fix applied so that we support all versions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my mind, having hotfixes implies that we support multiple release versions. Otherwise, if we only support the current version, then there is no need of hotfix or release branches. We can just apply the fix on 'main', and create a new release.

The hotfix should be a minimal change to address a specific issue on a release. The current version (on 'develop') should be our focus, so it makes sense to merge it there. We can merge it to other releases as see fit.

In any case, I think the chance of having to do a hotfix is pretty small since most deployer will stick with the latest version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ruixhuang 83ac400

Let me know what you think of this to support the scenario you originally mentioned

```sh
git checkout main
git merge release/1.0.2
```
5. Tag this new release with an updated version number.
```sh
git tag -a v(new_version) -m "v1.0.2"
git push origin --tags
```
6. Merge the hotfix into `develop` to ensure it's part of future releases.
```sh
git checkout develop
git merge release/1.0.2
```

## 3. Example
The following branching history visualization depicts a project which:
1. Released 1.0.0 based off the latest develop at the time
2. Released 1.0.1 based off 1.0.0 for a hotfix
3. Released 1.1.0 based off the latest develop at the time
<img src="https://github.com/dydxprotocol/v4-chain/assets/3445394/53e12dcc-84b6-4f51-9a16-0ecb19288d64">

This example can be recreated with [mermaid.live's tool](https://mermaid.live/) and the following code.
```
gitGraph
commit id:"1.0.0"
branch "develop"
commit id:"commit_a"
commit id:"commit_b"
branch release/1.0.0
checkout release/1.0.0
commit id:"commit_b (same HEAD)"
checkout develop
commit id:"commit_c"
merge release/1.0.0
commit id:"commit_d"
checkout main
merge release/1.0.0 tag:"v1.0.0"
checkout release/1.0.0
branch release/1.0.1
commit id:"commit_b (same HEAD) "
commit id:"commit_e (polish)"
checkout "develop"
merge release/1.0.1
checkout main
merge release/1.0.1 tag: "v1.0.1"
checkout develop
commit id: "commit_f"
commit id: "commit_g"
commit id: "commit_h"
branch release/1.1.0
checkout release/1.1.0
commit id:"commit_h (same head)"
checkout main
merge release/1.1.0 tag: "v1.1.0"
```

## 4. Release Management

The presence of release branches adds an extra layer of stability, as they remain available for any future needs for referencing or hotfixing that specific release.

## 5. Conclusion

This branching strategy and hotfix procedure ensure a robust framework for continuous development, stable production releases, and efficient deployment of critical fixes. It emphasizes the importance of team collaboration, communication, and a structured approach to managing code lifecycles.

62 changes: 62 additions & 0 deletions docs/forced_update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Forced Update Guide

This document outlines how to force app users to update to a particular version.

## 1. When to force an update

When Blockchain contract changes, FE app may need to be updated to be compatible. While web apps can be updated in sync with the contracts, native app users may not always update to the latest version.
</br>
</br>
Forced update is a mechanism to make sure the native app is compatible with the contracts, and Indexer endpoints.

## 2. Forced update strategy

Remote configuration is used to inform the app the minimum build number required.

### 2.1 Build number

Each app deployment has a build number, which is automatically incremented at build time. When the remote configuration contains a higher build number than the running app, app shows an UI to force the user to update the app.

### 2.2 Update URL

An URL is provided in the remote configuration. This URL should lead to the App Store to either

#### 2.2.1

Update the existing app

#### 2.2.2

Download a different app. This is a mechanism to release completely new app and prompt users of older app to migrate to the new app.

## 3. Remote Configuration

The remote configuration resides inside the Environment payload in the web app deployment, which should reside in **\public\configs\env.json**

Having the endpoint to the deployed web app is a necessary step to configure the native app deployment.

Different environments may have different app requirements. This enables the native apps to be deployed and tested with testnets before production network is deployed.

## 4. Sample Payload

In each environment, there is an optional **apps** payload.

```
"apps": {
"ios": {
"minimalVersion": "1.0",
"build":40000,
"url": "https://apps.apple.com/app/dydx/id1234567890"
}
}
```


**ios** and **android** is used to identify the requirments for iOS or Android apps.

**minimalVersion** used by the app to display required version. It is used for displaying only.

**build** is the minimum build number to be compatible with the environment.

**url** is the URL to the app on the App Store or Google Play Store.

6 changes: 4 additions & 2 deletions dydxV4/dydxV4.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2539,7 +2539,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.1;
MARKETING_VERSION = 0.1.0;
PRODUCT_BUNDLE_IDENTIFIER = exchangeV4.dydx.trading;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) _iOS";
Expand All @@ -2563,7 +2563,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.1;
MARKETING_VERSION = 0.1.0;
PRODUCT_BUNDLE_IDENTIFIER = exchangeV4.dydx.trading;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -2586,6 +2586,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 0.1.0;
PRODUCT_BUNDLE_IDENTIFIER = www.craziapps.dydxTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
Expand All @@ -2606,6 +2607,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 0.1.0;
PRODUCT_BUNDLE_IDENTIFIER = www.craziapps.dydxTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
117 changes: 116 additions & 1 deletion dydxV4/dydxV4/Assets.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -1 +1,116 @@
{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]}
{
"images": [
{
"idiom": "ios-marketing",
"filename": "AppIcon-1024x1024.png",
"scale": "1x",
"size": "1024x1024"
},
{
"idiom": "iphone",
"filename": "AppIcon-180x180.png",
"scale": "3x",
"size": "60x60"
},
{
"idiom": "ipad",
"filename": "AppIcon-167x167.png",
"scale": "2x",
"size": "83.5x83.5"
},
{
"idiom": "ipad",
"filename": "AppIcon-152x152.png",
"scale": "2x",
"size": "76x76"
},
{
"idiom": "iphone",
"filename": "AppIcon-120x120.png",
"scale": "3x",
"size": "40x40"
},
{
"idiom": "iphone",
"filename": "AppIcon-120x120.png",
"scale": "2x",
"size": "60x60"
},
{
"idiom": "iphone",
"filename": "AppIcon-87x87.png",
"scale": "3x",
"size": "29x29"
},
{
"idiom": "ipad",
"filename": "AppIcon-80x80.png",
"scale": "2x",
"size": "40x40"
},
{
"idiom": "iphone",
"filename": "AppIcon-80x80.png",
"scale": "2x",
"size": "40x40"
},
{
"idiom": "ipad",
"filename": "AppIcon-76x76.png",
"scale": "1x",
"size": "76x76"
},
{
"idiom": "iphone",
"filename": "AppIcon-60x60.png",
"scale": "3x",
"size": "20x20"
},
{
"idiom": "ipad",
"filename": "AppIcon-58x58.png",
"scale": "2x",
"size": "29x29"
},
{
"idiom": "iphone",
"filename": "AppIcon-58x58.png",
"scale": "2x",
"size": "29x29"
},
{
"idiom": "ipad",
"filename": "AppIcon-40x40.png",
"scale": "1x",
"size": "40x40"
},
{
"idiom": "iphone",
"filename": "AppIcon-40x40.png",
"scale": "2x",
"size": "20x20"
},
{
"idiom": "ipad",
"filename": "AppIcon-40x40.png",
"scale": "2x",
"size": "20x20"
},
{
"idiom": "ipad",
"filename": "AppIcon-29x29.png",
"scale": "1x",
"size": "29x29"
},
{
"idiom": "ipad",
"filename": "AppIcon-20x20.png",
"scale": "1x",
"size": "20x20"
}
],
"info": {
"version": 1,
"author": "fastlane"
}
}
2 changes: 2 additions & 0 deletions dydxV4/dydxV4/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
<key>RecordOnStart</key>
<false/>
</dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
Comment on lines +47 to +48
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding this prevents us from having to manually indicate the apps exemption for app store encryption policy

<key>LSApplicationQueriesSchemes</key>
<array>
<string>rainbow</string>
Expand Down
Loading
Loading