Skip to content

Commit 694b16f

Browse files
authored
Merge pull request #110 from codex-storage/feature/release-tests-cleanup
Release tests cleanup
2 parents 10b0136 + 58ed7ad commit 694b16f

File tree

63 files changed

+1251
-128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1251
-128
lines changed

.github/workflows/run-continuous-tests.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ env:
8080
TESTS_TARGET_DURATION: 2d
8181
TESTS_FILTER: ""
8282
TESTS_CLEANUP: true
83-
JOB_MANIFEST: docker/continuous-tests-job.yaml
83+
JOB_MANIFEST: docker/job-continuous-tests.yaml
8484
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
8585
KUBE_VERSION: v1.28.2
8686

@@ -146,7 +146,7 @@ jobs:
146146
if: false
147147
run: |
148148
# Variables
149-
# We need more than 300 seconds because Auto Scaler may take 3 minutes to tun a node
149+
# We need more than 300 seconds because Auto Scaler may take 3 minutes to run a node
150150
duration=600
151151
namespace="${{ env.NAMESPACE }}"
152152
pod=$(kubectl get pod --selector job-name=${{ env.NAMEPREFIX }} -o jsonpath="{.items[0].metadata.name}")

.github/workflows/run-dist-tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ env:
3232
NAMEPREFIX: d-tests-runner
3333
NAMESPACE: default
3434
COMMAND: dotnet test Tests/CodexTests
35-
JOB_MANIFEST: docker/dist-tests-job.yaml
35+
JOB_MANIFEST: docker/job-dist-tests.yaml
3636
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
3737
KUBE_VERSION: v1.28.2
3838

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
name: Run Release Tests
2+
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
codexdockerimage:
8+
description: "Codex Docker image (example: 'codexstorage/nim-codex:0.1.8-dist-tests')"
9+
required: true
10+
type: string
11+
workflow_call:
12+
inputs:
13+
codexdockerimage:
14+
description: "Codex Docker image (example: 'codexstorage/nim-codex:0.1.8-dist-tests')"
15+
required: true
16+
type: string
17+
18+
19+
env:
20+
SOURCE: ${{ format('{0}/{1}', github.server_url, github.repository) }}
21+
BRANCH: ${{ github.ref_name }}
22+
CODEXDOCKERIMAGE: codexstorage/nim-codex:latest-dist-tests
23+
TEST_TYPE: release-tests
24+
NAMEPREFIX: r-tests
25+
NAMESPACE: default
26+
JOB_MANIFEST: docker/job-release-tests.yaml
27+
COMMAND: dotnet test Tests/CodexReleaseTests
28+
DURATION: 7200
29+
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
30+
KUBE_VERSION: v1.30.5
31+
32+
33+
jobs:
34+
run_tests:
35+
name: Run Release Tests
36+
runs-on: ubuntu-latest
37+
steps:
38+
- name: Checkout
39+
uses: actions/checkout@v4
40+
with:
41+
repository: ${{ inputs.workflow_source }}
42+
43+
- name: Variables
44+
run: |
45+
RUNID=$(date +%Y%m%d-%H%M%S)
46+
echo "RUNID=${RUNID}" >> $GITHUB_ENV
47+
echo "TESTID=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
48+
[[ -n "${{ inputs.source }}" ]] && echo "SOURCE=${{ inputs.source }}" >>"$GITHUB_ENV" || echo "SOURCE=${{ env.SOURCE }}" >>"$GITHUB_ENV"
49+
[[ -n "${{ inputs.branch }}" ]] && echo "BRANCH=${{ inputs.branch }}" >>"$GITHUB_ENV" || echo "BRANCH=${{ env.BRANCH }}" >>"$GITHUB_ENV"
50+
[[ -n "${{ inputs.codexdockerimage }}" ]] && echo "CODEXDOCKERIMAGE=${{ inputs.codexdockerimage }}" >>"$GITHUB_ENV" || echo "CODEXDOCKERIMAGE=${{ env.CODEXDOCKERIMAGE }}" >>"$GITHUB_ENV"
51+
[[ -n "${{ inputs.nameprefix }}" ]] && NAMEPREFIX="`awk '{ print tolower($0) }' <<< ${{ inputs.nameprefix }}`" || NAMEPREFIX="`awk '{ print tolower($0) }' <<< ${{ env.NAMEPREFIX }}`"
52+
echo "NAMEPREFIX=${NAMEPREFIX}-${RUNID}" >>"$GITHUB_ENV"
53+
[[ -n "${{ inputs.namespace }}" ]] && echo "NAMESPACE=${{ inputs.namespace }}" >>"$GITHUB_ENV" || echo "NAMESPACE=${{ env.NAMESPACE }}" >>"$GITHUB_ENV"
54+
[[ -n "${{ inputs.command }}" ]] && COMMAND="${{ inputs.command }}" || COMMAND="${{ env.COMMAND }}"
55+
echo "COMMAND=$(jq -c 'split(" ")' <<< '"'${COMMAND}'"')" >>"$GITHUB_ENV"
56+
57+
- name: Kubectl - Install ${{ env.KUBE_VERSION }}
58+
uses: azure/setup-kubectl@v4
59+
with:
60+
version: ${{ env.KUBE_VERSION }}
61+
62+
- name: Kubectl - Kubeconfig
63+
run: |
64+
mkdir -p "${HOME}"/.kube
65+
echo "${{ env.KUBE_CONFIG }}" | base64 -d > "${HOME}"/.kube/config
66+
67+
- name: Kubectl - Create Job to run tests
68+
run: |
69+
envsubst < ${{ env.JOB_MANIFEST }} | kubectl apply -f -
70+
71+
- name: Tests Identification
72+
run: |
73+
echo "----"
74+
echo "Repository: ${{ env.SOURCE }}"
75+
echo "Branch: ${{ env.BRANCH }}"
76+
echo "Runner job: ${{ env.NAMEPREFIX }}"
77+
echo "Runner pod: $(kubectl get pod --selector job-name=${{ env.NAMEPREFIX }} -ojsonpath='{.items[0].metadata.name}')"
78+
echo "Runner namespace: ${{ env.NAMESPACE }}"
79+
echo "----"
80+
81+
- name: Show Runner logs
82+
run: |
83+
# Variables
84+
# We need more than 300 seconds because Auto Scaler may take 3 minutes to tun a node
85+
duration=${{ env.DURATION }}
86+
namespace="${{ env.NAMESPACE }}"
87+
pod=$(kubectl get pod --selector job-name=${{ env.NAMEPREFIX }} -o jsonpath="{.items[0].metadata.name}")
88+
89+
# Check Pod status
90+
WAIT=120
91+
SECONDS=0
92+
sleep=1
93+
while (( SECONDS < WAIT )); do
94+
phase=$(kubectl get pod ${pod} -n ${namespace} -o jsonpath="{.status.phase}")
95+
[[ "${phase}" == "Running" ]] && { echo "Pod $pod is in $phase state - Get the logs"; break; } || { echo "Pod $pod is in $phase state - Retry in $sleep seconds / $((WAIT - SECONDS))"; }
96+
sleep $sleep
97+
done
98+
99+
# Get logs
100+
timeout $duration \
101+
kubectl logs $pod \
102+
-n $namespace \
103+
-f \
104+
--tail=-1 \
105+
--timestamps || true

Framework/GethConnector/GethConnector.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CodexContractsPlugin;
2+
using CodexContractsPlugin.Marketplace;
23
using GethPlugin;
34
using Logging;
45

@@ -18,18 +19,29 @@ public class GethConnector
1819
return null;
1920
}
2021

22+
var gethNode = new CustomGethNode(log, GethInput.GethHost, GethInput.GethPort, GethInput.PrivateKey);
23+
24+
var config = GetCodexMarketplaceConfig(gethNode, GethInput.MarketplaceAddress);
25+
2126
var contractsDeployment = new CodexContractsDeployment(
27+
config: config,
2228
marketplaceAddress: GethInput.MarketplaceAddress,
2329
abi: GethInput.ABI,
2430
tokenAddress: GethInput.TokenAddress
2531
);
2632

27-
var gethNode = new CustomGethNode(log, GethInput.GethHost, GethInput.GethPort, GethInput.PrivateKey);
2833
var contracts = new CodexContractsAccess(log, gethNode, contractsDeployment);
2934

3035
return new GethConnector(gethNode, contracts);
3136
}
3237

38+
private static MarketplaceConfig GetCodexMarketplaceConfig(IGethNode gethNode, string marketplaceAddress)
39+
{
40+
var func = new ConfigurationFunctionBase();
41+
var response = gethNode.Call<ConfigurationFunctionBase, ConfigurationOutputDTO>(marketplaceAddress, func);
42+
return response.ReturnValue1;
43+
}
44+
3345
private GethConnector(IGethNode gethNode, ICodexContracts codexContracts)
3446
{
3547
GethNode = gethNode;

ProjectPlugins/CodexContractsPlugin/CodexContractsAccess.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using GethPlugin;
33
using Logging;
44
using Nethereum.ABI;
5+
using Nethereum.Hex.HexConvertors.Extensions;
56
using Nethereum.Util;
67
using NethereumWorkflow;
78
using Newtonsoft.Json;
@@ -24,6 +25,7 @@ public interface ICodexContracts
2425
ICodexContractsEvents GetEvents(BlockInterval blockInterval);
2526
EthAddress? GetSlotHost(Request storageRequest, decimal slotIndex);
2627
RequestState GetRequestState(Request request);
28+
void WaitUntilNextPeriod();
2729
}
2830

2931
[JsonConverter(typeof(StringEnumConverter))]
@@ -114,6 +116,15 @@ public RequestState GetRequestState(Request request)
114116
return gethNode.Call<RequestStateFunction, RequestState>(Deployment.MarketplaceAddress, func);
115117
}
116118

119+
public void WaitUntilNextPeriod()
120+
{
121+
log.Log("Waiting until next proof period...");
122+
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
123+
var periodSeconds = (int)Deployment.Config.Proofs.Period;
124+
var secondsLeft = now % periodSeconds;
125+
Thread.Sleep(TimeSpan.FromSeconds(secondsLeft + 1));
126+
}
127+
117128
private ContractInteractions StartInteraction()
118129
{
119130
return new ContractInteractions(log, gethNode);

ProjectPlugins/CodexContractsPlugin/CodexContractsDeployment.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
namespace CodexContractsPlugin
1+
using CodexContractsPlugin.Marketplace;
2+
3+
namespace CodexContractsPlugin
24
{
35
public class CodexContractsDeployment
46
{
5-
public CodexContractsDeployment(string marketplaceAddress, string abi, string tokenAddress)
7+
public CodexContractsDeployment(MarketplaceConfig config, string marketplaceAddress, string abi, string tokenAddress)
68
{
9+
Config = config;
710
MarketplaceAddress = marketplaceAddress;
811
Abi = abi;
912
TokenAddress = tokenAddress;
1013
}
1114

15+
public MarketplaceConfig Config { get; }
1216
public string MarketplaceAddress { get; }
1317
public string Abi { get; }
1418
public string TokenAddress { get; }

ProjectPlugins/CodexContractsPlugin/CodexContractsStarter.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using KubernetesWorkflow;
55
using KubernetesWorkflow.Types;
66
using Logging;
7+
using Newtonsoft.Json;
78
using Utils;
89

910
namespace CodexContractsPlugin
@@ -34,6 +35,7 @@ public CodexContractsDeployment Deploy(CoreInterface ci, IGethNode gethNode)
3435
try
3536
{
3637
var result = DeployContract(container, workflow, gethNode);
38+
3739
workflow.Stop(containers, waitTillStopped: false);
3840
Log("Container stopped.");
3941
return result;
@@ -75,9 +77,20 @@ private CodexContractsDeployment DeployContract(RunningContainer container, ISta
7577

7678
Time.WaitUntil(() => interaction.IsSynced(marketplaceAddress, abi), nameof(DeployContract));
7779

78-
Log("Synced. Codex SmartContracts deployed.");
80+
Log("Synced. Codex SmartContracts deployed. Getting configuration...");
81+
82+
var config = GetMarketplaceConfiguration(marketplaceAddress, gethNode);
83+
84+
Log("Got config: " + JsonConvert.SerializeObject(config));
7985

80-
return new CodexContractsDeployment(marketplaceAddress, abi, tokenAddress);
86+
return new CodexContractsDeployment(config, marketplaceAddress, abi, tokenAddress);
87+
}
88+
89+
private MarketplaceConfig GetMarketplaceConfiguration(string marketplaceAddress, IGethNode gethNode)
90+
{
91+
var func = new ConfigurationFunctionBase();
92+
var response = gethNode.Call<ConfigurationFunctionBase, ConfigurationOutputDTO>(marketplaceAddress, func);
93+
return response.ReturnValue1;
8194
}
8295

8396
private void EnsureCompatbility(string abi, string bytecode)

ProjectPlugins/CodexContractsPlugin/ContractInteractions.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ public ContractInteractions(ILog log, IGethNode gethNode)
2323
public string GetTokenAddress(string marketplaceAddress)
2424
{
2525
log.Debug(marketplaceAddress);
26-
var function = new GetTokenFunction();
27-
28-
return gethNode.Call<GetTokenFunction, string>(marketplaceAddress, function);
26+
var function = new TokenFunctionBase();
27+
return gethNode.Call<TokenFunctionBase, string>(marketplaceAddress, function);
2928
}
3029

3130
public string GetTokenName(string tokenAddress)
@@ -111,11 +110,6 @@ private bool IsContractAvailable(string marketplaceAddress, string marketplaceAb
111110
}
112111
}
113112

114-
[Function("token", "address")]
115-
public class GetTokenFunction : FunctionMessage
116-
{
117-
}
118-
119113
[Function("name", "string")]
120114
public class GetTokenNameFunction : FunctionMessage
121115
{

ProjectPlugins/CodexContractsPlugin/TestTokenExtensions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ public override string ToString()
4646
return new TestToken(a.TstWei + b.TstWei);
4747
}
4848

49+
public static TestToken operator -(TestToken a, TestToken b)
50+
{
51+
return new TestToken(a.TstWei - b.TstWei);
52+
}
53+
54+
public static TestToken operator *(TestToken a, int b)
55+
{
56+
return new TestToken(a.TstWei * b);
57+
}
58+
4959
public static bool operator <(TestToken a, TestToken b)
5060
{
5161
return a.TstWei < b.TstWei;

ProjectPlugins/CodexPlugin/CodexAccess.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,22 @@ public DebugInfo GetDebugInfo()
3232
return mapper.Map(OnCodex(api => api.GetDebugInfoAsync()));
3333
}
3434

35+
public string GetSpr()
36+
{
37+
return CrashCheck(() =>
38+
{
39+
var endpoint = GetEndpoint();
40+
var json = endpoint.HttpGetString("spr");
41+
var response = JsonConvert.DeserializeObject<SprResponse>(json);
42+
return response!.Spr;
43+
});
44+
}
45+
46+
private class SprResponse
47+
{
48+
public string Spr { get; set; } = string.Empty;
49+
}
50+
3551
public DebugPeer GetDebugPeer(string peerId)
3652
{
3753
// Cannot use openAPI: debug/peer endpoint is not specified there.
@@ -80,6 +96,18 @@ public Stream DownloadFile(string contentId, Action<Failure> onFailure)
8096
return fileResponse.Stream;
8197
}
8298

99+
public LocalDataset DownloadStreamless(ContentId cid)
100+
{
101+
var response = OnCodex(api => api.DownloadNetworkAsync(cid.Id));
102+
return mapper.Map(response);
103+
}
104+
105+
public LocalDataset DownloadManifestOnly(ContentId cid)
106+
{
107+
var response = OnCodex(api => api.DownloadNetworkManifestAsync(cid.Id));
108+
return mapper.Map(response);
109+
}
110+
83111
public LocalDatasetList LocalFiles()
84112
{
85113
return mapper.Map(OnCodex(api => api.ListDataAsync()));

ProjectPlugins/CodexPlugin/CodexNode.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@ public interface ICodexNode : IHasContainer, IHasMetricsScrapeTarget, IHasEthAdd
1515
string GetName();
1616
string GetPeerId();
1717
DebugInfo GetDebugInfo();
18+
string GetSpr();
1819
DebugPeer GetDebugPeer(string peerId);
1920
ContentId UploadFile(TrackedFile file);
2021
ContentId UploadFile(TrackedFile file, Action<Failure> onFailure);
2122
ContentId UploadFile(TrackedFile file, string contentType, string contentDisposition, Action<Failure> onFailure);
2223
TrackedFile? DownloadContent(ContentId contentId, string fileLabel = "");
2324
TrackedFile? DownloadContent(ContentId contentId, Action<Failure> onFailure, string fileLabel = "");
25+
LocalDataset DownloadStreamless(ContentId cid);
26+
LocalDataset DownloadManifestOnly(ContentId cid);
2427
LocalDatasetList LocalFiles();
2528
CodexSpace Space();
2629
void ConnectToPeer(ICodexNode node);
@@ -128,6 +131,11 @@ public DebugInfo GetDebugInfo()
128131
return debugInfo;
129132
}
130133

134+
public string GetSpr()
135+
{
136+
return CodexAccess.GetSpr();
137+
}
138+
131139
public DebugPeer GetDebugPeer(string peerId)
132140
{
133141
return CodexAccess.GetDebugPeer(peerId);
@@ -192,6 +200,16 @@ public ContentId UploadFile(TrackedFile file, string contentType, string content
192200
return file;
193201
}
194202

203+
public LocalDataset DownloadStreamless(ContentId cid)
204+
{
205+
return CodexAccess.DownloadStreamless(cid);
206+
}
207+
208+
public LocalDataset DownloadManifestOnly(ContentId cid)
209+
{
210+
return CodexAccess.DownloadManifestOnly(cid);
211+
}
212+
195213
public LocalDatasetList LocalFiles()
196214
{
197215
return CodexAccess.LocalFiles();

0 commit comments

Comments
 (0)