Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 038e6cd2 authored by Arnau Vàzquez's avatar Arnau Vàzquez
Browse files

Merge branch 'master' into 'production'

Deploy progressive rollout

See merge request !35
parents ecab51fe 1f770f47
Loading
Loading
Loading
Loading
+56 −0
Original line number Original line Diff line number Diff line
@@ -43,6 +43,21 @@ then finally visit http://localhost/ to see the REST Server up and running.
- Full builds should be uploaded into `builds/full` directory.
- Full builds should be uploaded into `builds/full` directory.
- Delta builds should be uploaded into `builds/delta` directory.
- Delta builds should be uploaded into `builds/delta` directory.


### Folder Structure for Builds

All the builds , props, md5sum and other files of a device and channel needs to be in common folder. You must follow below folder structure. The same folder name must be used in API.

```shell
builds/full/<CHANNEL>/<DEVICE>
```

For Example, All builds and other files of star2lte for stable channel will be in  `/builds/full/stable/star2lte`

### Device and Channel fields are now mandatory in API 

The fields `device` and `channel` are mandatory and `incremental` is an optional field in an API (which is used to get the builds).


## How to specify allowed migration paths
## How to specify allowed migration paths


- You can specify migration rules (whether an upgrade from a version to a version is allowed or not) by creating a migration_paths.json file in your build directory
- You can specify migration rules (whether an upgrade from a version to a version is allowed or not) by creating a migration_paths.json file in your build directory
@@ -56,6 +71,30 @@ then finally visit http://localhost/ to see the REST Server up and running.
- The contents should be read as: Upgrades from major version 9 to major version 9 and to major version 10 are allowed. Upgrades from major version 10 to major version 10 and to major version 11 are allowed.
- The contents should be read as: Upgrades from major version 9 to major version 9 and to major version 10 are allowed. Upgrades from major version 10 to major version 10 and to major version 11 are allowed.
- Current version is always available as an upgrade (if a more recent build is found), even if file is not available (for backwards compatibility too).
- Current version is always available as an upgrade (if a more recent build is found), even if file is not available (for backwards compatibility too).


## How to set incremental rollout percentage in build config file

- You can specify incremental rollout rules by adding values in `config.json` file. You can add the file only if you want percentage incremental rollout for a build.
- The format of file name will be : `<BUILD_NAME>.zip.config.json`

```shell
$ cd builds/full/test/guacamoleb/
$ tree
.
├── e.x.xx-xxyyzz-guacamoleb.zip # the full ROM zip file
└── e.x.xx-xxyyzz-guacamoleb.zip.config.json # the ROM build.config.json file
```

- E.g. : Suppose builds for "guacamoleb" devices are stored at "/mnt/rom/builds/full/test/guacamoleb". The file "/mnt/rom/builds/full/test/guacamoleb/e.x.xx-xxyyzz-guacamoleb.zip.config.json" should then have contents like:
```json
    { 
        "rollout": {
            "percentage": 20
        }   
    }
```
- The `percentage` value must be between 0 to 100. Do not add `%` sign after the value. 
- The `config.json` file is not mandatory. In case it does not exist, a build will consider a 100% rollout percentage.

### ONLY for LineageOS 15.x and newer
### ONLY for LineageOS 15.x and newer


If you are willing to use this project on top of your LineageOS 15.x ( or newer ) ROM builds, you may have noticed that the file named `build.prop` have been removed inside your ZIP file, and has been instead integrated within your `system.new.dat` file, which is basically an ext4 image ( you can find out more here: https://source.android.com/devices/tech/ota/block ).
If you are willing to use this project on top of your LineageOS 15.x ( or newer ) ROM builds, you may have noticed that the file named `build.prop` have been removed inside your ZIP file, and has been instead integrated within your `system.new.dat` file, which is basically an ext4 image ( you can find out more here: https://source.android.com/devices/tech/ota/block ).
@@ -82,6 +121,23 @@ I am not sure how much this may help anyway, but this must be used as an extreme


Feel free to use this [simple script](https://github.com/julianxhokaxhiu/LineageOTAUnitTest) made with NodeJS. Instructions are included.
Feel free to use this [simple script](https://github.com/julianxhokaxhiu/LineageOTAUnitTest) made with NodeJS. Instructions are included.


## LineageOTA Unit Testing

You can cerate new `{FILENAME}Test.php` in `tests` folder. Use `vendor/bin/phpunit tests` command in CLI to run the tests.
In every test file, in `setUp()` function, you must set below details for valid test results :

```properties
$this->romType = '{device}'; 
$this->deviceType = '{type}';
$this->incrementalVersion = '{incr}';

{device} - Device name
{type} - Build type
{incr} - Incremental version

```


## How to integrate within your ROM
## How to integrate within your ROM


In order to integrate this REST Server within your ROM you have two possibilities: you can make use of the `build.prop` ( highly suggested ), or you can patch directly the `android_packages_apps_CMUpdater` package ( not suggested ).
In order to integrate this REST Server within your ROM you have two possibilities: you can make use of the `build.prop` ( highly suggested ), or you can patch directly the `android_packages_apps_CMUpdater` package ( not suggested ).
+3 −0
Original line number Original line Diff line number Diff line
@@ -57,5 +57,8 @@
  },
  },
  "scripts": {
  "scripts": {
    "serve": "php -S 0.0.0.0:8000"
    "serve": "php -S 0.0.0.0:8000"
  },
  "require-dev": {
    "phpunit/phpunit": "^9"
  }
  }
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -60,5 +60,5 @@


    $app = new CmOta($logger);
    $app = new CmOta($logger);
    $app
    $app
    ->setConfig( 'basePath', $protocol.$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']) )
    ->setConfig( 'basePath', rtrim( $protocol.$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']) , "/" ) )
    ->run();
    ->run();
+20 −19
Original line number Original line Diff line number Diff line
@@ -129,6 +129,7 @@
                  );
                  );
    
    
                  Flight::json($ret);
                  Flight::json($ret);
    
            });
            });
        }
        }


+49 −2
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@
        private $incremental = '';
        private $incremental = '';
        private $filePath = '';
        private $filePath = '';
        private $buildProp = '';
        private $buildProp = '';
        private $confProp = '';
        private $uid = null;
        private $uid = null;
        private $size = '';
        private $size = '';
        private $logger = null;
        private $logger = null;
@@ -82,6 +83,7 @@
            // - builds/CURRENT_ZIP_FILE.zip/system/build.prop
            // - builds/CURRENT_ZIP_FILE.zip/system/build.prop
            // - builds/CURRENT_ZIP_FILE.zip.prop ( which must exist )
            // - builds/CURRENT_ZIP_FILE.zip.prop ( which must exist )
            $this->buildProp = explode("\n", @file_get_contents($this->getPropFilePath()));
            $this->buildProp = explode("\n", @file_get_contents($this->getPropFilePath()));
            $this->confProp = $this->getConfProp();
            // Try to fetch build.prop values. In some cases, we can provide a fallback, in other a null value will be given
            // Try to fetch build.prop values. In some cases, we can provide a fallback, in other a null value will be given
            $this->timestamp = intval($this->getBuildPropValue('ro.build.date.utc') ?? filemtime($this->filePath));
            $this->timestamp = intval($this->getBuildPropValue('ro.build.date.utc') ?? filemtime($this->filePath));
            $this->incremental = $this->getBuildPropValue('ro.build.version.incremental') ?? '';
            $this->incremental = $this->getBuildPropValue('ro.build.version.incremental') ?? '';
@@ -510,4 +512,49 @@
        {
        {
            return is_callable($func) && false === stripos(ini_get('disable_functions'), $func);
            return is_callable($func) && false === stripos(ini_get('disable_functions'), $func);
        }
        }

        /**
         * Check if the current build is valid with multiple conditions
         * @param type $params The params dictionary inside the current POST request
         * @return boolean True if valid, False if not.
         */
        public function includeInResults($params)
        {
            return $this->isValid($params) && $this->checkRollout() && $this->getSize() > 0;
        }

        /**
         * Return the correct config file path (depending of version)
         * @return string
         */
        private function getConfigFilePath()
        {
            return file_exists($this->filePath . '.config.json') ? $this->filePath . '.config.json' : '';
        }

        /**
         * Return the all values from config file path
         * @return JSON if valid otherwise null
         */
        private function getConfProp(){
            $configFilePath = $this->getConfigFilePath();
            return ($configFilePath) ?  json_decode( file_get_contents($configFilePath) , true) : array();
        }

        /**
         * Return if rollout successful or not for a build
         * @return boolean
         */
        public function checkRollout()
        {
            $rolloutpercentage = isset($this->confProp['rollout']['percentage']) ? (int) $this->confProp['rollout']['percentage'] : 100;
            if ($rolloutpercentage <= 0 || $rolloutpercentage > 100) {
                return TRUE;
            }
            $rand_number = rand(1, 100);
            if ($rand_number > $rolloutpercentage) {
                return FALSE;
            }
            return TRUE;
        }
    }
    }
 No newline at end of file
Loading