Skip to content

Commit

Permalink
feat: canary builds
Browse files Browse the repository at this point in the history
  • Loading branch information
NeKzor committed May 11, 2024
1 parent 14728d9 commit 914a054
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 37 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/CD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ jobs:
name: sar-linux
path: sar.so
if-no-files-found: error
- name: Upload to dl.sar.portal2.sr
if: github.ref == 'refs/heads/master' && github.repository_owner == 'p2sr'
env:
DL_SAR_API_TOKEN: ${{ secrets.DL_SAR_API_TOKEN }}
run: |
SAR_VERSION=$(git describe --tags)
curl -X "POST" \
-H "Authorization: Bearer $DL_SAR_API_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "version=$(echo $SAR_VERSION | awk -F- '{print $1}')" \
-F "sar_version=$SAR_VERSION" \
-F "system=linux" \
-F "commit=$GITHUB_SHA" \
-F "branch=$GITHUB_REF_NAME" \
-F "count=1" \
-F "hashes[0]=$(sha256sum sar.so | cut -d ' ' -f 1)" \
-F "files[0]=@sar.so" \
"https://dl.sar.portal2.sr/api/v1/upload"
build-win:
name: Windows Build
runs-on: windows-2019
Expand Down Expand Up @@ -57,6 +75,27 @@ jobs:
name: sar-windows-pdb
path: bin\sar.pdb
if-no-files-found: error
- name: Upload to dl.sar.portal2.sr
if: github.ref == 'refs/heads/master' && github.repository_owner == 'p2sr'
shell: bash
env:
DL_SAR_API_TOKEN: ${{ secrets.DL_SAR_API_TOKEN }}
run: |
SAR_VERSION=$(git describe --tags)
curl -X "POST" \
-H "Authorization: Bearer $DL_SAR_API_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "version=$(echo $SAR_VERSION | awk -F- '{print $1}')" \
-F "sar_version=$SAR_VERSION" \
-F "system=windows" \
-F "commit=$GITHUB_SHA" \
-F "branch=$GITHUB_REF_NAME" \
-F "count=2" \
-F "hashes[0]=$(sha256sum bin/sar.dll | cut -d ' ' -f 1)" \
-F "hashes[1]=$(sha256sum bin/sar.pdb | cut -d ' ' -f 1)" \
-F "files[0]=@bin/sar.dll" \
-F "files[1]=@bin/sar.pdb" \
"https://dl.sar.portal2.sr/api/v1/upload"
release:
name: Release
if: github.repository == 'p2sr/SourceAutoRecord'
Expand Down
59 changes: 49 additions & 10 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ on:
push:
branches: '**'
tags-ignore: '**'
paths-ignore:
- '.github/*'
- '.github/workflows/CD.yml'
- '.mailmap'
- '.gitattributes'
- '.gitignore'
- 'docs/**'
- 'livesplit/**'
- '**.md'
- 'LICENSE'
paths:
- 'lib/**'
- 'src/**'
- 'Makefile'
pull_request:
branches: '**'
paths:
- 'lib/**'
- 'src/**'
- 'Makefile'
workflow_dispatch:

jobs:
Expand All @@ -40,6 +39,25 @@ jobs:
name: sar-linux
path: sar.so
if-no-files-found: error
- name: Upload to dl.sar.portal2.sr
if: github.ref == 'refs/heads/master' && github.repository_owner == 'p2sr'
env:
DL_SAR_API_TOKEN: ${{ secrets.DL_SAR_API_TOKEN }}
run: |
SAR_VERSION=$(git describe --tags)
curl -X "POST" \
-H "Authorization: Bearer $DL_SAR_API_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "version=$(echo $SAR_VERSION | awk -F- '{print $1}')-canary" \
-F "sar_version=$SAR_VERSION-canary" \
-F "system=linux" \
-F "commit=$GITHUB_SHA" \
-F "branch=$GITHUB_REF_NAME" \
-F "count=1" \
-F "hashes[0]=$(sha256sum sar.so | cut -d ' ' -f 1)" \
-F "files[0]=@sar.so" \
"https://dl.sar.portal2.sr/api/v1/upload"
build-win:
name: Windows Build
runs-on: windows-2019
Expand All @@ -64,3 +82,24 @@ jobs:
bin\sar.dll
bin\sar.pdb
if-no-files-found: error
- name: Upload to dl.sar.portal2.sr
if: github.ref == 'refs/heads/master' && github.repository_owner == 'p2sr'
shell: bash
env:
DL_SAR_API_TOKEN: ${{ secrets.DL_SAR_API_TOKEN }}
run: |
SAR_VERSION=$(git describe --tags)
curl -X "POST" \
-H "Authorization: Bearer $DL_SAR_API_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "version=$(echo $SAR_VERSION | awk -F- '{print $1}')-canary" \
-F "sar_version=$SAR_VERSION-canary" \
-F "system=windows" \
-F "commit=$GITHUB_SHA" \
-F "branch=$GITHUB_REF_NAME" \
-F "count=2" \
-F "hashes[0]=$(sha256sum bin/sar.dll | cut -d ' ' -f 1)" \
-F "hashes[1]=$(sha256sum bin/sar.pdb | cut -d ' ' -f 1)" \
-F "files[0]=@bin/sar.dll" \
-F "files[1]=@bin/sar.pdb" \
"https://dl.sar.portal2.sr/api/v1/upload"
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ $(ODIR)/%.o: $(SDIR)/%.cpp
$(CXX) $(CXXFLAGS) -MMD -c $< -o $@

src/Version.hpp: .FORCE
echo "#define SAR_VERSION \"$(VERSION)\"" >"$@"
if [ "$$RELEASE_BUILD" ]; then echo "#define SAR_VERSION \"$(VERSION)\"" >"$@"; fi
if [ -z "$$RELEASE_BUILD" ]; then echo "#define SAR_VERSION \"$(VERSION)-canary\"" >"$@"; fi
if [ -z "$$RELEASE_BUILD" ]; then echo "#define SAR_DEV_BUILD 1" >>"$@"; fi
echo "#define SAR_DEMO_SIGN_PUBKEY { $$DEMO_SIGN_PUBKEY }" >>"$@"
echo "#define SAR_DEMO_SIGN_PRIVKEY { $$DEMO_SIGN_PRIVKEY }" >>"$@"
Expand Down
8 changes: 6 additions & 2 deletions genversion.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
for /f "tokens=* usebackq" %%x in (`git describe --tags`) do (set version=%%x)
echo #define SAR_VERSION "%version%">Version.hpp
if "%RELEASE_BUILD%"=="" echo #define SAR_DEV_BUILD 1>>Version.hpp
if "%RELEASE_BUILD%"=="" (
echo #define SAR_VERSION "%version%-canary">Version.hpp
echo #define SAR_DEV_BUILD 1>>Version.hpp
) else (
echo #define SAR_VERSION "%version%">Version.hpp
)
echo #define SAR_DEMO_SIGN_PUBKEY { %DEMO_SIGN_PUBKEY% }>>Version.hpp
echo #define SAR_DEMO_SIGN_PRIVKEY { %DEMO_SIGN_PRIVKEY% }>>Version.hpp
105 changes: 81 additions & 24 deletions src/Features/Updater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,19 @@ static std::thread g_worker;
struct SarVersion {
unsigned components[MAX_VERSION_COMPONENTS];
unsigned pre;
bool canary;
};

#define DL_SAR_HOST "https://dl.sar.portal2.sr"

enum class Channel {
Release,
PreRelease,
Canary,
};

static std::optional<SarVersion> getVersionComponents(const char *str) {
SarVersion v = {0};
SarVersion v = {0, 0, false};
v.pre = UINT_MAX;

size_t i = 0;
Expand All @@ -59,17 +68,29 @@ static std::optional<SarVersion> getVersionComponents(const char *str) {
}

if (!*str) return v;
if (memcmp(str, "-pre", 4)) return {};

if (Utils::EndsWith(std::string(str), "-canary")) {
v.canary = true;
return v;
}

if (memcmp(str, "-pre", 4)) {
return {};
}
str += 4;
char *end;
v.pre = strtol(str, &end, 10);
if (str == end || *end) return {};
return v;
}

static bool isNewerVersion(const char *verStr) {
static bool isNewerVersion(std::string& verStr) {
auto version = getVersionComponents(verStr.c_str());
auto current = getVersionComponents(SAR_VERSION);
auto version = getVersionComponents(verStr);

if ((version && version->canary) || (current && current->canary)) {
return strcmp(SAR_VERSION, verStr.c_str()) != 0;
}

if (!current) {
THREAD_PRINT("Cannot compare version numbers on non-release version\n");
Expand Down Expand Up @@ -130,7 +151,10 @@ static bool downloadFile(const char *url, const char *path) {

fclose(f);

return res == CURLE_OK;
long code;
curl_easy_getinfo(g_curl, CURLINFO_RESPONSE_CODE, &code);

return res == CURLE_OK && code == 200;
}

static std::string request(const char *url) {
Expand All @@ -149,14 +173,17 @@ static std::string request(const char *url) {

CURLcode res = curl_easy_perform(g_curl);

return res == CURLE_OK ? response : "";
long code;
curl_easy_getinfo(g_curl, CURLINFO_RESPONSE_CODE, &code);

return res == CURLE_OK && code == 200 ? response : "";
}

static bool getLatestVersion(std::string *name, std::string *dlUrl, std::string *pdbUrl, bool allowPre) {
static bool getLatestVersion(std::string *name, std::string *dlUrl, std::string *pdbUrl, Channel channel) {
// FIXME: This will fail if the API rate limit is saturated (bruteforcing? many instances?)
// maybe cache the response for a couple minutes - AMJ 2024-04-25
json11::Json res;
if (allowPre) {
if (channel == Channel::PreRelease) {
std::string err;
res = json11::Json::parse(request("https://api.github.com/repos/p2sr/SourceAutoRecord/releases"), err);
if (err != "") {
Expand All @@ -167,7 +194,27 @@ static bool getLatestVersion(std::string *name, std::string *dlUrl, std::string
} catch (...) {
return false;
}

} else if (channel == Channel::Canary) {
std::string err;
res = json11::Json::parse(request(DL_SAR_HOST "/api/v1/latest/canary"), err);
if (err != "") {
return false;
}
try {
*name = res["sar_version"].string_value();

auto url = std::string(DL_SAR_HOST "/") + res["version"].string_value();
#if _WIN32
auto systemPath = "/windows/";
*pdbUrl = url + systemPath + PDB_ASSET_NAME;
#else
auto systemPath = "/linux/";
#endif
*dlUrl = url + systemPath + ASSET_NAME;
return true;
} catch (...) {
return false;
}
} else {
std::string err;
res = json11::Json::parse(request("https://api.github.com/repos/p2sr/SourceAutoRecord/releases/latest"), err);
Expand Down Expand Up @@ -226,36 +273,36 @@ static std::string createTempPath(const char *filename) {
return p.string();
}

void checkUpdate(bool allowPre) {
void checkUpdate(Channel channel) {
std::string name, dlUrl, pdbUrl;

THREAD_PRINT("Querying for latest version...\n");

if (!getLatestVersion(&name, &dlUrl, &pdbUrl, allowPre)) {
if (!getLatestVersion(&name, &dlUrl, &pdbUrl, channel)) {
THREAD_PRINT("An error occurred\n");
return;
}

THREAD_PRINT("Latest version is %s\n", name.c_str());

if (!isNewerVersion(name.c_str())) {
if (!isNewerVersion(name)) {
THREAD_PRINT("You're all up-to-date!\n");
} else {
THREAD_PRINT("Update with sar_update, or at %s\n", dlUrl.c_str());
}
}

void doUpdate(bool allowPre, bool exitOnSuccess, bool force) {
void doUpdate(Channel channel, bool exitOnSuccess, bool force) {
std::string name, dlUrl, pdbUrl;

THREAD_PRINT("Querying for latest version...\n");

if (!getLatestVersion(&name, &dlUrl, &pdbUrl, allowPre)) {
if (!getLatestVersion(&name, &dlUrl, &pdbUrl, channel)) {
THREAD_PRINT("An error occurred\n");
return;
}

if (!force && !isNewerVersion(name.c_str())) {
if (!force && !isNewerVersion(name)) {
THREAD_PRINT("You're already up-to-date!\n");
return;
}
Expand Down Expand Up @@ -316,25 +363,35 @@ void doUpdate(bool allowPre, bool exitOnSuccess, bool force) {
}
}

CON_COMMAND(sar_check_update, "sar_check_update [release|pre] - check whether the latest version of SAR is being used\n") {
CON_COMMAND(sar_check_update, "sar_check_update [release|pre|canary] - check whether the latest version of SAR is being used\n") {
if (args.ArgC() > 2) {
return THREAD_PRINT(sar_check_update.ThisPtr()->m_pszHelpString);
}

bool allowPre = args.ArgC() == 2 && !strcmp(args[1], "pre");
auto channel = Channel::Release;

if (!strcmp(args[1], "pre")) {
channel = Channel::PreRelease;
} else if (!strcmp(args[1], "pre")) {
channel = Channel::Canary;
}

if (g_worker.joinable()) g_worker.join();
g_worker = std::thread(checkUpdate, allowPre);
g_worker = std::thread(checkUpdate, channel);
}

CON_COMMAND(sar_update, "sar_update [release|pre] [exit] [force] - update SAR to the latest version. If exit is given, exit the game upon successful update; if force is given, always re-install, even if it may be a downgrade\n") {
bool allowPre = false, exitOnSuccess = false, force = false;
CON_COMMAND(sar_update, "sar_update [release|pre|canary] [exit] [force] - update SAR to the latest version. If exit is given, exit the game upon successful update; if force is given, always re-install, even if it may be a downgrade\n") {
auto channel = Channel::Release;
auto exitOnSuccess = false;
auto force = false;

for (int i = 1; i < args.ArgC(); ++i) {
if (!strcmp(args[i], "pre")) {
allowPre = true;
channel = Channel::PreRelease;
} else if (!strcmp(args[i], "canary")) {
channel = Channel::Canary;
} else if (!strcmp(args[i], "release")) {
allowPre = false;
channel = Channel::Release;
} else if (!strcmp(args[i], "exit")) {
exitOnSuccess = true;
} else if (!strcmp(args[i], "force")) {
Expand All @@ -347,9 +404,9 @@ CON_COMMAND(sar_update, "sar_update [release|pre] [exit] [force] - update SAR to
}

if (g_worker.joinable()) g_worker.join();
g_worker = std::thread(doUpdate, allowPre, exitOnSuccess, force);
g_worker = std::thread(doUpdate, channel, exitOnSuccess, force);
}

ON_EVENT(SAR_UNLOAD) {
if (g_worker.joinable()) g_worker.detach();
if (g_worker.joinable()) g_worker.join();
}

0 comments on commit 914a054

Please sign in to comment.