Skip to content

Commit

Permalink
Release v1.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
operate-services-sdk-bot committed Jun 12, 2024
1 parent 302f508 commit 5f95e87
Show file tree
Hide file tree
Showing 152 changed files with 10,577 additions and 271 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,23 @@ All notable changes to UGS CLI will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [1.5.0] - 2024-06-12

### Fixed
- Now supporting multiple entries on `--services` and `--key` options.
- Fix Cloud Content Delivery issue of content upload failure or timeouts for large files.

### Added
- Added Cloud Save module service commands. Run `ugs cloud-save -h` to show usage.
- Added support for [Matchmaker](https://docs.unity.com/ugs/en-us/manual/matchmaker/manual/matchmaker-overview) to Deploy and Fetch.

## [1.4.0] - 2024-04-22
### Fixed
- Improve Cloud Code script in-script parameter wrong argument type parsing error
- Cloud Content Delivery Module Service commands. Run `ugs ccd -h` to show usage.

### Changed
- The env list command now outputs as a table
- The `env list` command now outputs as a table

## [1.3.0] - 2024-02-29
### Added
Expand Down
2 changes: 1 addition & 1 deletion Samples/Deploy/Leaderboards/lbsample.lb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"UpdateType": "keepBest",
"Name": "My Leaderboard",
"ResetConfig": {
"Start": "2023-08-25T00:00:00-04:00",
"Start": "2033-08-25T00:00:00-04:00",
"Schedule": "0 12 1 * *"
},
"TieringConfig": {
Expand Down
5 changes: 5 additions & 0 deletions Samples/Deploy/Matchmaker/environment-config.mme
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"$schema": "https://ugs-config-schemas.unity3d.com/v1/matchmaker/matchmaker-environment-config.schema.json",
"enabled": true,
"defaultQueueName": "default-queue"
}
67 changes: 67 additions & 0 deletions Samples/Deploy/Matchmaker/queue.mmq
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"$schema": "https://ugs-config-schemas.unity3d.com/v1/matchmaker/matchmaker-queue.schema.json",
"name": "default-queue",
"enabled": true,
"maxPlayersPerTicket": 2,
"defaultPool": {
"variants": [],
"name": "default-pool",
"enabled": true,
"timeoutSeconds": 90,
"matchLogic": {
"matchDefinition": {
"teams": [
{
"name": "Team",
"teamCount": {
"min": 2,
"max": 2,
"relaxations": []
},
"playerCount": {
"min": 1,
"max": 2,
"relaxations": []
},
"teamRules": []
}
],
"matchRules": [
{
"source": "Players.ExternalData.CloudSave.Skill",
"name": "skill-diff",
"type": "Difference",
"reference": 500,
"overlap": 0.0,
"enableRule": false,
"not": false,
"relaxations": []
},
{
"source": "Players.QosResults.Latency",
"name": "QoS",
"type": "LessThanEqual",
"reference": 100,
"overlap": 0.0,
"enableRule": false,
"not": false,
"relaxations": [
{
"type": "ReferenceControl.Replace",
"ageType": "Oldest",
"atSeconds": 30.0,
"value": 200
}
]
}
]
},
"name": "Default Pool Rules",
"backfillEnabled": false
},
"matchHosting": {
"type": "MatchId",
}
},
"filteredPools": []
}
29 changes: 29 additions & 0 deletions Samples/Deploy/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
[Deploy Economy](#deploy-economy)<br>
[Deploy Leaderboards](#deploy-leaderboards)<br>
[Deploy Access](#deploy-access)<br>
[Deploy Matchmaker](#deploy-matchmaker)<br>

## Deploy Cloud Code Script

Expand Down Expand Up @@ -176,6 +177,29 @@ To create a deployable access file, you need a `.ac` file with the following pat
}
```
Please take [sample-policy.ac] as an example. For more details, please check [Access Control Documentation Portal] and/or [Access Control schema].

## Deploy Matchmaker

Run command from [Samples/Deploy] directory:
```
ugs deploy ./Matchmaker
```

You will find the resource from [environment-config.mme] and [queue.mmq] published in your dashboard
for the configured project and environment.

### Create Matchmaker Files

To create a deployable access file,
you need `.mme` and `.mmq` files, each containing a json with the required information for the specific resource.

File Schemas:
- [Matchmaker Environment Config resource schema]
- [Matchmaker Queue resource schema]

Please take [environment-config.mme] and [queue.mmq] as examples.
For more details, please check the [Matchmaker Admin API].

## Deploy all Samples
Run command from [Samples/Deploy] directory:
```
Expand Down Expand Up @@ -217,6 +241,9 @@ You will find all the contents deployed in your dashboard for the configured pro
[Leaderboards API]: https://services.docs.unity.com/leaderboards-admin/
[Leaderboards schema]: https://ugs-config-schemas.unity3d.com/v1/leaderboards.schema.json
[Economy resource schemas]: https://services.docs.unity.com/economy-admin/v2#tag/Economy-Admin/operation/addConfigResource
[Matchmaker Admin API]: https://services.docs.unity.com/matchmaker-admin/
[Matchmaker Environment Config resource schema]: https://ugs-config-schemas.unity3d.com/v1/matchmaker/matchmaker-environment-config.schema.json
[Matchmaker Queue resource schema]: https://ugs-config-schemas.unity3d.com/v1/matchmaker/matchmaker-queue.schema.json
[Declare parameters in the script]: https://docs.unity.com/cloud-code/authoring-scripts-editor.html#Declare_parameters_in_the_script
[Module.ccm]: /Samples/Deploy/CloudCode/Module/Module.ccm
[Script.js]: /Samples/Deploy/CloudCode/Script/Script.js
Expand All @@ -237,3 +264,5 @@ You will find all the contents deployed in your dashboard for the configured pro
[Triggers Documentation Portal]: https://docs.unity.com/ugs/en-us/manual/cloud-code/manual/triggers
[Triggers Schema]: https://ugs-config-schemas.unity3d.com/v1/triggers.schema.json
[my-triggers.tr]: /Samples/Deploy/Triggers/my-triggers.tr
[environment-config.mme]: /Samples/Deploy/Matchmaker/environment-config.mme
[queue.mmq]: /Samples/Deploy/Matchmaker/queue.mmq
37 changes: 37 additions & 0 deletions Third Party Notices.md
Original file line number Diff line number Diff line change
Expand Up @@ -596,3 +596,40 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

<hr>

Component Name: Compare-Net-Objects

Licence Type: Microsoft Public License (Ms-PL)

Copyright (c) 2021 Greg Finzer

https://github.com/GregFinzer/Compare-Net-Objects

This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.

Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.

A "contribution" is the original software, or any additions or changes to the software.

A "contributor" is any person that distributes its contribution under this license.

"Licensed patents" are a contributor's patent claims that read directly on its contribution.

Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.

(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.

Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.

(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.

(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.

(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.

(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public async Task GetAsyncForPolicyWithNoStatements()
[Test]
public async Task GetAsyncForPolicyWithStatements()
{
var policy = TestMocks.GetPolicy(new List<Statement>(){TestMocks.GetStatement()});
var policy = TestMocks.GetPolicy(new List<ProjectStatement>(){TestMocks.GetProjectStatement()});
m_MockAccessService.Setup(r => r.GetPolicyAsync(k_TestProjectId, k_TestEnvironmentId, CancellationToken.None)).ReturnsAsync(policy);

var authoringStatements = new List<AccessControlStatement>()
Expand All @@ -86,7 +86,7 @@ public async Task GetAsyncForPolicyWithStatements()
public async Task UpsertAsyncSuccessfully()
{
var authoringStatements = new List<AccessControlStatement>(){TestMocks.GetAuthoringStatement("sid-1"), TestMocks.GetAuthoringStatement("sid-2")};
var policy = TestMocks.GetPolicy(new List<Statement>(){TestMocks.GetStatement("sid-1"), TestMocks.GetStatement("sid-2")});
var policy = TestMocks.GetPolicy(new List<ProjectStatement>(){TestMocks.GetProjectStatement("sid-1"), TestMocks.GetProjectStatement("sid-2")});
await m_ProjectAccessClient!.UpsertAsync(authoringStatements);
m_MockAccessService.Verify(ac => ac.UpsertProjectAccessCaCAsync(k_TestProjectId, k_TestEnvironmentId, policy, CancellationToken.None), Times.Once);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public void UpsertPolicyAsync_InvalidInput()
[Test]
public async Task UpsertPlayerPolicyAsync_Valid()
{
m_PlayerPolicyApi.Setup(a => a.UpsertPlayerPolicyAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Policy>(),
m_PlayerPolicyApi.Setup(a => a.UpsertPlayerPolicyAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<PlayerPolicyUpsert>(),
It.IsAny<int>(), CancellationToken.None));

await m_AccessService!.UpsertPlayerPolicyAsync(
Expand All @@ -221,7 +221,7 @@ public async Task UpsertPlayerPolicyAsync_Valid()
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<Policy>(),
It.IsAny<PlayerPolicyUpsert>(),
It.IsAny<int>(),
It.IsAny<CancellationToken>()),
Times.Once);
Expand All @@ -231,7 +231,7 @@ public async Task UpsertPlayerPolicyAsync_Valid()
public void UpsertPlayerPolicyAsync_Invalid_ApiThrowsError()
{
m_PlayerPolicyApi.Setup(a => a.UpsertPlayerPolicyAsync(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<string>(), It.IsAny<Policy>(), It.IsAny<int>(), CancellationToken.None)).Throws<ApiException>();
It.IsAny<string>(), It.IsAny<PlayerPolicyUpsert>(), It.IsAny<int>(), CancellationToken.None)).Throws<ApiException>();

Assert.ThrowsAsync<CliException>(
() => m_AccessService!.UpsertPlayerPolicyAsync(TestValues.ValidProjectId, TestValues.ValidEnvironmentId, TestValues.ValidPlayerId,
Expand Down Expand Up @@ -343,9 +343,9 @@ public void DeletePlayerPolicyStatementsAsync_InvalidInput()
[Test]
public async Task UpsertProjectAccessCaCAsync_Valid()
{
var statements = new List<Statement>()
var statements = new List<ProjectStatement>()
{
TestMocks.GetStatement()
TestMocks.GetProjectStatement()
};
m_ProjectPolicyApi.Setup(a => a.UpsertPolicyAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Policy>(),
It.IsAny<int>(), CancellationToken.None));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="NUnit.Analyzers" Version="3.5.0" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
<PackageReference Include="Unity.Services.Gateway.AccessApiV1.Generated" Version="1.0.1" />
<PackageReference Include="Unity.Services.Gateway.AccessApiV1.Generated" Version="1.1.0" />
<ProjectReference Include="..\Unity.Services.Cli.Access\Unity.Services.Cli.Access.csproj" />
<ProjectReference Include="..\Unity.Services.Cli.TestUtils\Unity.Services.Cli.TestUtils.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,27 @@ namespace Unity.Services.Cli.Access.UnitTest.Utils;

class TestMocks
{
public static Statement GetStatement(string sid = "statement-1")
public static ProjectStatement GetProjectStatement(string sid = "statement-1")
{
List<string> action = new List<string>();
action.Add("*");

Statement statement = new Statement(sid: sid, action: action, effect: "Deny", principal: "Player",
ProjectStatement statement = new ProjectStatement(sid: sid, action: action, effect: "Deny", principal: "Player",
resource: "urn:ugs:*");
return statement;
}

public static Policy GetPolicy(List<Statement> statements)
public static PlayerStatement GetPlayerStatement(string sid = "statement-1")
{
List<string> action = new List<string>();
action.Add("*");

PlayerStatement statement = new PlayerStatement(sid: sid, action: action, effect: "Deny", principal: "Player",
resource: "urn:ugs:*");
return statement;
}

public static Policy GetPolicy(List<ProjectStatement> statements)
{
var policy = new Policy(statements);
return policy;
Expand Down Expand Up @@ -47,8 +57,8 @@ public static AccessControlStatement GetAuthoringStatement(

public static PlayerPolicy GetPlayerPolicy()
{
List<Statement> statements = new List<Statement>();
statements.Add(GetStatement());
List<PlayerStatement> statements = new List<PlayerStatement>();
statements.Add(GetPlayerStatement());

PlayerPolicy playerPolicy = new PlayerPolicy(playerId: TestValues.ValidPlayerId, statements);
return playerPolicy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static List<AccessControlStatement> GetAuthoringStatementsFromPolicy(Policy poli
static Policy GetPolicyFromAuthoringStatements(IReadOnlyList<AccessControlStatement> authoringStatements)
{
var statements = authoringStatements.Select(
s => new Statement(
s => new ProjectStatement(
sid: s.Sid,
action: s.Action,
effect: s.Effect,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@ public async Task UpsertPlayerPolicyAsync(string projectId, string environmentId

var jsonString = ReadFile(file);

Policy? policy;
PlayerPolicyUpsert? policy;
try
{
policy = JsonConvert.DeserializeObject<Policy>(jsonString, new JsonSerializerSettings
policy = JsonConvert.DeserializeObject<PlayerPolicyUpsert>(jsonString, new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Error,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<ProjectReference Include="..\Unity.Services.Cli.ServiceAccountAuthentication\Unity.Services.Cli.ServiceAccountAuthentication.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Unity.Services.Gateway.AccessApiV1.Generated" Version="1.0.1" />
<PackageReference Include="Unity.Services.Gateway.AccessApiV1.Generated" Version="1.1.0" />
<PackageReference Include="Unity.Services.Tooling.Editor.AccessControl.Authoring.Core" Version="0.0.3" />
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ public class AuthoringInput : CommonInput
"--services",
"-s"
},
"The name(s) of the service(s) to perform the command on.");
"The name(s) of the service(s) to perform the command on.")
{
Arity = ArgumentArity.OneOrMore,
AllowMultipleArgumentsPerToken = true
};

[InputBinding(nameof(ServiceOptions))]
public IReadOnlyList<string> Services { get; set; } = new List<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using Unity.Services.CloudCode.Authoring.Editor.Core.Model;
using Unity.Services.Gateway.CloudCodeApiV1.Generated.Client;
using Unity.Services.Gateway.CloudCodeApiV1.Generated.Model;
using APILanguage = Unity.Services.Gateway.CloudCodeApiV1.Generated.Model.Language;
using CoreLanguage = Unity.Services.CloudCode.Authoring.Editor.Core.Model.Language;

namespace Unity.Services.Cli.CloudCode.UnitTest.Authoring;
Expand Down Expand Up @@ -100,7 +99,7 @@ public async Task GetModuleSucceed()
{
var apiResponse = new GetModuleResponse(
name: k_ModuleName,
language: APILanguage.JS);
language: "JS");
m_MockService.Setup(c => c.GetModuleAsync(TestValues.ValidProjectId, TestValues.ValidEnvironmentId, k_ModuleName, CancellationToken.None))
.ReturnsAsync(apiResponse);
var moduleName = new ScriptName(k_ModuleName);
Expand Down
Loading

0 comments on commit 5f95e87

Please sign in to comment.