feat: expose application version and update CI release workflow
Release / release (pull_request) Successful in 1m4s
Release / release (pull_request) Successful in 1m4s
This commit is contained in:
@@ -1,48 +0,0 @@
|
|||||||
name: Build and Upload Binaries
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-upload:
|
|
||||||
runs-on: build-htz-01
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
- name: Build Windows and Linux AMD64 binaries
|
|
||||||
run: |
|
|
||||||
mkdir -p dist
|
|
||||||
|
|
||||||
# Build Linux amd64 and Windows amd64 binaries
|
|
||||||
docker run --rm -v ${{ github.workspace }}:/workspace -w /workspace cr.jdbnet.co.uk/jdbnet/wails-builder:latest bash -c "
|
|
||||||
# Install frontend dependencies
|
|
||||||
cd frontend && npm install && cd ..
|
|
||||||
|
|
||||||
# Linux amd64
|
|
||||||
wails build -platform linux/amd64 -tags webkit2_41 -clean
|
|
||||||
cp build/bin/goexplore dist/goexplore-linux-amd64
|
|
||||||
|
|
||||||
# Windows amd64
|
|
||||||
wails build -platform windows/amd64 -clean -nsis
|
|
||||||
cp build/bin/GoExplore-amd64-installer.exe dist/goexplore-windows-installer.exe
|
|
||||||
"
|
|
||||||
|
|
||||||
- name: Upload to Cloudflare R2
|
|
||||||
env:
|
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
|
||||||
AWS_DEFAULT_REGION: auto
|
|
||||||
R2_ENDPOINT: ${{ secrets.R2_ENDPOINT_URL }}
|
|
||||||
run: |
|
|
||||||
aws s3 cp dist/goexplore-linux-amd64 s3://apps/goexplore/goexplore-linux-amd64 --endpoint-url "$R2_ENDPOINT"
|
|
||||||
aws s3 cp dist/goexplore-windows-installer.exe s3://apps/goexplore/goexplore-windows-installer.exe --endpoint-url "$R2_ENDPOINT"
|
|
||||||
|
|
||||||
- name: Clean up
|
|
||||||
run: sudo rm -rf dist build/bin/*
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
types: [closed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
if: github.event.pull_request.merged == true && startsWith(github.head_ref, 'v')
|
||||||
|
runs-on: build-htz-01
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Extract Version
|
||||||
|
id: get_version
|
||||||
|
run: |
|
||||||
|
# Remove 'v' prefix for some contexts if needed, but we'll use it raw
|
||||||
|
RAW_VERSION=${{ github.head_ref }}
|
||||||
|
CLEAN_VERSION=${RAW_VERSION#v}
|
||||||
|
echo "VERSION=${RAW_VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
echo "CLEAN_VERSION=${CLEAN_VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Build Binaries
|
||||||
|
run: |
|
||||||
|
mkdir -p dist
|
||||||
|
|
||||||
|
# Build Linux amd64 and Windows amd64 binaries using custom docker image
|
||||||
|
docker run --rm -v ${{ github.workspace }}:/workspace -w /workspace cr.jdbnet.co.uk/jdbnet/wails-builder:latest bash -c "
|
||||||
|
# Inject version into wails.json for NSIS & executable properties
|
||||||
|
sed -i 's/\"productVersion\": \".*\"/\"productVersion\": \"${{ steps.get_version.outputs.CLEAN_VERSION }}\"/' wails.json
|
||||||
|
|
||||||
|
# Install frontend dependencies
|
||||||
|
cd frontend && npm install && cd ..
|
||||||
|
|
||||||
|
# Linux amd64
|
||||||
|
wails build -platform linux/amd64 -tags webkit2_41 -clean -ldflags \"-X main.Version=${{ steps.get_version.outputs.VERSION }}\"
|
||||||
|
cp build/bin/goexplore dist/goexplore-linux-amd64
|
||||||
|
|
||||||
|
# Windows amd64
|
||||||
|
wails build -platform windows/amd64 -clean -nsis -ldflags \"-X main.Version=${{ steps.get_version.outputs.VERSION }}\"
|
||||||
|
cp build/bin/GoExplore-amd64-installer.exe dist/goexplore-windows-installer.exe
|
||||||
|
"
|
||||||
|
|
||||||
|
# - name: Generate Changelog
|
||||||
|
# id: changelog
|
||||||
|
# uses: https://github.com/metcalfc/changelog-generator@v4.6.2
|
||||||
|
# with:
|
||||||
|
# myToken: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Create Gitea Release
|
||||||
|
uses: https://gitea.com/actions/gitea-release-action@v1
|
||||||
|
with:
|
||||||
|
tag_name: ${{ steps.get_version.outputs.VERSION }}
|
||||||
|
name: GoExplore ${{ steps.get_version.outputs.VERSION }}
|
||||||
|
body: ${{ steps.changelog.outputs.changelog }}
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
|
files: |
|
||||||
|
dist/goexplore-linux-amd64
|
||||||
|
dist/goexplore-windows-installer.exe
|
||||||
|
|
||||||
|
- name: Upload to Cloudflare R2
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_DEFAULT_REGION: auto
|
||||||
|
R2_ENDPOINT: ${{ secrets.R2_ENDPOINT_URL }}
|
||||||
|
run: |
|
||||||
|
aws s3 cp dist/goexplore-linux-amd64 s3://apps/goexplore/goexplore-linux-amd64 --endpoint-url "$R2_ENDPOINT"
|
||||||
|
aws s3 cp dist/goexplore-windows-installer.exe s3://apps/goexplore/goexplore-windows-installer.exe --endpoint-url "$R2_ENDPOINT"
|
||||||
|
|
||||||
|
- name: Clean up
|
||||||
|
run: sudo rm -rf dist build/bin/*
|
||||||
@@ -44,6 +44,10 @@ func (a *App) startup(ctx context.Context) {
|
|||||||
a.ctx = ctx
|
a.ctx = ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) GetVersion() string {
|
||||||
|
return Version
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) GetConnections() []config.ConnectionConfig {
|
func (a *App) GetConnections() []config.ConnectionConfig {
|
||||||
if a.cfg == nil {
|
if a.cfg == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
<div class="sidebar-header">
|
<div class="sidebar-header">
|
||||||
<img src="./src/assets/appicon.png" alt="Icon" style="width: 24px; height: 24px; margin-right: 0.5rem;"/>
|
<img src="./src/assets/appicon.png" alt="Icon" style="width: 24px; height: 24px; margin-right: 0.5rem;"/>
|
||||||
<span>GoExplore</span>
|
<span>GoExplore</span>
|
||||||
|
<span id="app-version" style="font-size: 0.7rem; color: var(--text-secondary); margin-left: 0.5rem; border: 1px solid var(--border); padding: 0.1rem 0.3rem; border-radius: 4px;"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="conn-list" id="conn-list">
|
<div class="conn-list" id="conn-list">
|
||||||
<!-- Connections will be populated here -->
|
<!-- Connections will be populated here -->
|
||||||
|
|||||||
+23
-15
@@ -1,4 +1,4 @@
|
|||||||
import { ListDir, GetConnections, SaveConnection, DeleteConnection, Delete, Rename, PromptUploadFiles, PromptUploadDirectory, PromptDownload, TransferItems, GetTransfers, ClearTransfers } from '../wailsjs/go/main/App.js';
|
import { GetVersion, ListDir, GetConnections, SaveConnection, DeleteConnection, Delete, Rename, PromptUploadFiles, PromptUploadDirectory, PromptDownload, TransferItems, GetTransfers, ClearTransfers } from '../wailsjs/go/main/App.js';
|
||||||
|
|
||||||
let currentConn = 'local';
|
let currentConn = 'local';
|
||||||
let currentPath = '';
|
let currentPath = '';
|
||||||
@@ -24,6 +24,14 @@ async function init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const version = await GetVersion();
|
||||||
|
const vSpan = document.getElementById('app-version');
|
||||||
|
if (vSpan && version) {
|
||||||
|
vSpan.innerText = version;
|
||||||
|
}
|
||||||
|
} catch (e) { }
|
||||||
|
|
||||||
await loadConnections();
|
await loadConnections();
|
||||||
await loadDirectory(currentConn, currentPath);
|
await loadDirectory(currentConn, currentPath);
|
||||||
|
|
||||||
@@ -46,7 +54,7 @@ async function init() {
|
|||||||
await SaveConnection(conn, secret);
|
await SaveConnection(conn, secret);
|
||||||
closeConnModal();
|
closeConnModal();
|
||||||
loadConnections();
|
loadConnections();
|
||||||
} catch(err) {
|
} catch (err) {
|
||||||
alert("Failed to save connection: " + err);
|
alert("Failed to save connection: " + err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -70,7 +78,7 @@ async function loadConnections() {
|
|||||||
list.appendChild(el);
|
list.appendChild(el);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,17 +136,17 @@ window.updateProtocolFields = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.deleteConnection = async () => {
|
window.deleteConnection = async () => {
|
||||||
if(!confirm("Are you sure you want to delete this connection?")) return;
|
if (!confirm("Are you sure you want to delete this connection?")) return;
|
||||||
const id = document.getElementById('conn-id').value;
|
const id = document.getElementById('conn-id').value;
|
||||||
try {
|
try {
|
||||||
await DeleteConnection(id);
|
await DeleteConnection(id);
|
||||||
closeConnModal();
|
closeConnModal();
|
||||||
if(currentConn === id) {
|
if (currentConn === id) {
|
||||||
switchConn('local');
|
switchConn('local');
|
||||||
} else {
|
} else {
|
||||||
loadConnections();
|
loadConnections();
|
||||||
}
|
}
|
||||||
} catch(err) {
|
} catch (err) {
|
||||||
alert("Failed to delete connection: " + err);
|
alert("Failed to delete connection: " + err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -168,7 +176,7 @@ async function loadDirectory(connId, path) {
|
|||||||
if (a.is_dir !== b.is_dir) return a.is_dir ? -1 : 1;
|
if (a.is_dir !== b.is_dir) return a.is_dir ? -1 : 1;
|
||||||
|
|
||||||
let cmp = 0;
|
let cmp = 0;
|
||||||
switch(sortField) {
|
switch (sortField) {
|
||||||
case 'name':
|
case 'name':
|
||||||
cmp = a.name.localeCompare(b.name);
|
cmp = a.name.localeCompare(b.name);
|
||||||
break;
|
break;
|
||||||
@@ -223,9 +231,9 @@ async function loadDirectory(connId, path) {
|
|||||||
selectedItems = [];
|
selectedItems = [];
|
||||||
allRows.forEach(r => r.classList.remove('selected'));
|
allRows.forEach(r => r.classList.remove('selected'));
|
||||||
|
|
||||||
for(let i=startIdx; i<=endIdx; i++) {
|
for (let i = startIdx; i <= endIdx; i++) {
|
||||||
const row = allRows[i];
|
const row = allRows[i];
|
||||||
if(row.dataset.path) {
|
if (row.dataset.path) {
|
||||||
row.classList.add('selected');
|
row.classList.add('selected');
|
||||||
selectedItems.push({
|
selectedItems.push({
|
||||||
path: row.dataset.path,
|
path: row.dataset.path,
|
||||||
@@ -251,7 +259,7 @@ async function loadDirectory(connId, path) {
|
|||||||
}
|
}
|
||||||
tbody.appendChild(tr);
|
tbody.appendChild(tr);
|
||||||
});
|
});
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
tbody.innerHTML = `<tr><td colspan="4" style="color: var(--error)">Error: ${e}</td></tr>`;
|
tbody.innerHTML = `<tr><td colspan="4" style="color: var(--error)">Error: ${e}</td></tr>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,7 +287,7 @@ function formatDate(dateString) {
|
|||||||
if (!dateString) return '-';
|
if (!dateString) return '-';
|
||||||
const d = new Date(dateString);
|
const d = new Date(dateString);
|
||||||
if (isNaN(d.getTime())) return dateString;
|
if (isNaN(d.getTime())) return dateString;
|
||||||
return `${String(d.getDate()).padStart(2, '0')}/${String(d.getMonth()+1).padStart(2, '0')}/${d.getFullYear()} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
return `${String(d.getDate()).padStart(2, '0')}/${String(d.getMonth() + 1).padStart(2, '0')}/${d.getFullYear()} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.setSort = (field) => {
|
window.setSort = (field) => {
|
||||||
@@ -300,7 +308,7 @@ window.clearTransfers = async () => {
|
|||||||
try {
|
try {
|
||||||
await ClearTransfers();
|
await ClearTransfers();
|
||||||
pollTransfers();
|
pollTransfers();
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -338,7 +346,7 @@ async function pollTransfers() {
|
|||||||
</div>`;
|
</div>`;
|
||||||
});
|
});
|
||||||
list.innerHTML = html;
|
list.innerHTML = html;
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -527,7 +535,7 @@ window.loadTransferDestDirectory = async (connId, path) => {
|
|||||||
}
|
}
|
||||||
tbody.appendChild(tr);
|
tbody.appendChild(tr);
|
||||||
});
|
});
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
tbody.innerHTML = `<tr><td style="color: var(--error)">Error: ${e}</td></tr>`;
|
tbody.innerHTML = `<tr><td style="color: var(--error)">Error: ${e}</td></tr>`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -540,7 +548,7 @@ window.executeTransfer = async () => {
|
|||||||
showTransfers();
|
showTransfers();
|
||||||
selectedItems = [];
|
selectedItems = [];
|
||||||
Array.from(document.querySelectorAll('#file-list tr')).forEach(r => r.classList.remove('selected'));
|
Array.from(document.querySelectorAll('#file-list tr')).forEach(r => r.classList.remove('selected'));
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
alert("Transfer failed: " + e);
|
alert("Transfer failed: " + e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+2
@@ -15,6 +15,8 @@ export function GetConnections():Promise<Array<config.ConnectionConfig>>;
|
|||||||
|
|
||||||
export function GetTransfers():Promise<Array<transfer.Transfer>>;
|
export function GetTransfers():Promise<Array<transfer.Transfer>>;
|
||||||
|
|
||||||
|
export function GetVersion():Promise<string>;
|
||||||
|
|
||||||
export function ListDir(arg1:string,arg2:string):Promise<Array<explorer.FileEntry>>;
|
export function ListDir(arg1:string,arg2:string):Promise<Array<explorer.FileEntry>>;
|
||||||
|
|
||||||
export function MkDir(arg1:string,arg2:string):Promise<void>;
|
export function MkDir(arg1:string,arg2:string):Promise<void>;
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ export function GetTransfers() {
|
|||||||
return window['go']['main']['App']['GetTransfers']();
|
return window['go']['main']['App']['GetTransfers']();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GetVersion() {
|
||||||
|
return window['go']['main']['App']['GetVersion']();
|
||||||
|
}
|
||||||
|
|
||||||
export function ListDir(arg1, arg2) {
|
export function ListDir(arg1, arg2) {
|
||||||
return window['go']['main']['App']['ListDir'](arg1, arg2);
|
return window['go']['main']['App']['ListDir'](arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ var assets embed.FS
|
|||||||
//go:embed build/appicon.png
|
//go:embed build/appicon.png
|
||||||
var icon []byte
|
var icon []byte
|
||||||
|
|
||||||
|
var Version string = "dev"
|
||||||
|
|
||||||
func installLinux() {
|
func installLinux() {
|
||||||
if runtime.GOOS != "linux" {
|
if runtime.GOOS != "linux" {
|
||||||
return
|
return
|
||||||
|
|||||||
+2
-1
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"info": {
|
"info": {
|
||||||
"companyName": "JDB-NET Limited",
|
"companyName": "JDB-NET Limited",
|
||||||
"productName": "GoExplore"
|
"productName": "GoExplore",
|
||||||
|
"productVersion": "0.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user