Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 0 additions & 42 deletions .claude/settings.local.json

This file was deleted.

1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
134 changes: 134 additions & 0 deletions .github/workflows/desktop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
name: Desktop Candidate

on:
push:
branches: [main, 'release/**']
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
desktop:
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
bundles: nsis
- os: macos-latest
bundles: app,dmg
- os: ubuntu-22.04
bundles: deb,appimage
runs-on: ${{ matrix.os }}
defaults:
run:
working-directory: desktop
env:
MACOSX_DEPLOYMENT_TARGET: '13.0'
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v5
with:
go-version: '1.27.x'
- uses: actions/setup-node@v5
with:
node-version: '22'
cache: npm
cache-dependency-path: desktop/package-lock.json
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: '1.92.0'
components: rustfmt, clippy
- name: Install Linux desktop libraries
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential libxdo-dev libssl-dev librsvg2-dev patchelf
- run: npm ci
- run: npm run build
- run: npx playwright install --with-deps chromium
- run: npm test
- run: npm run sidecar
- run: cargo fmt --manifest-path src-tauri/Cargo.toml -- --check
- run: cargo test --manifest-path src-tauri/Cargo.toml --locked
- name: Verify GLib backport under release optimization
if: runner.os == 'Linux'
run: cargo test --manifest-path src-tauri/Cargo.toml --locked --release glib_string_iteration
- run: cargo clippy --manifest-path src-tauri/Cargo.toml --locked -- -D warnings
- name: Build native installer without publishing
run: npm run desktop:build -- --bundles ${{ matrix.bundles }}
- name: Exercise Windows native webview and bundled engine
if: runner.os == 'Windows'
run: npm run test:native
- name: Verify sidecar and collect installers
shell: python
run: |
import hashlib
import json
import pathlib
import platform
import shutil
import subprocess
import tempfile

root = pathlib.Path.cwd()
sidecars = list((root / "src-tauri/binaries").glob("conceal-engine-*"))
assert len(sidecars) == 1, sidecars
engine = sidecars[0]
version = subprocess.check_output([engine, "version"], text=True)
assert version.strip() == "conceal v4.3.0-rc.1", version
catalog = json.loads(subprocess.check_output([engine, "action", "adapters"], text=True))
assert {a["id"] for a in catalog["adapters"]} == {"aws", "github"}
bundle = root / "src-tauri/target/release/bundle"
if platform.system() in {"Darwin", "Linux"}:
packaged_engines = list(bundle.rglob("conceal-engine"))
assert packaged_engines, "no engine found in native package staging"
for packaged in packaged_engines:
packaged_version = subprocess.check_output([packaged, "version"], text=True)
assert packaged_version.strip() == "conceal v4.3.0-rc.1", packaged
licenses = [p for p in bundle.rglob("LICENSE")
if p.parent.name == "glib" and p.parent.parent.name == "licenses"]
assert licenses, "GLib license missing from native package staging"
expected_license = (root / "src-tauri/vendor/glib/LICENSE").read_bytes()
assert all(p.read_bytes() == expected_license for p in licenses)
with tempfile.TemporaryDirectory() as directory:
state = pathlib.Path(directory) / "state"
args = [str(engine), "action", "--state-dir", str(state)]
proposal = json.loads(subprocess.check_output(args + [
"prepare", "--contract", str(root.parent / "examples/s3-contract.json"),
"--operation", "aws.s3.objects.list", "--resource", "example-backups"], text=True))
identifier = proposal["request"]["id"]
review = json.loads(subprocess.check_output(args + ["review", identifier], text=True))
assert review["can_approve"] and not review["can_execute"]
subprocess.run(args + ["approve", identifier, "--digest", proposal["digest"]], check=True)
subprocess.run(args + ["revoke", identifier], check=True)
denied = subprocess.run(args + ["execute", identifier], capture_output=True, text=True)
assert denied.returncode != 0 and "consumed or revoked" in denied.stderr
destination = root / "dist/packages"
destination.mkdir(parents=True, exist_ok=True)
installers = [p for p in bundle.rglob("*")
if p.is_file() and p.suffix in {".exe", ".dmg", ".deb", ".AppImage"}]
assert installers, "no native installer was produced"
for path in installers:
shutil.copy2(path, destination / path.name)
for name in ("README.md", "LICENSE", "SECURITY.md", "CONTRIBUTING.md"):
shutil.copy2(root.parent / name, destination / name)
notices = destination / "third-party/glib"
notices.mkdir(parents=True)
for name in ("LICENSE", "COPYRIGHT"):
shutil.copy2(root / "src-tauri/vendor/glib" / name, notices / name)
shutil.copy2(root / "src-tauri/vendor/README.md", notices / "BACKPORT.md")
shutil.copytree(root.parent / "docs", destination / "docs")
shutil.copytree(root.parent / "examples", destination / "examples")
entries = []
for path in sorted(destination.rglob("*")):
if path.is_file():
entries.append(hashlib.sha256(path.read_bytes()).hexdigest() + " " + path.relative_to(destination).as_posix())
(destination / "checksums.txt").write_text("\n".join(entries) + "\n")
- uses: actions/upload-artifact@v4
with:
name: desktop-${{ runner.os }}-${{ runner.arch }}
path: desktop/dist/packages/
if-no-files-found: error
193 changes: 73 additions & 120 deletions .github/workflows/go-test.yml
Original file line number Diff line number Diff line change
@@ -1,134 +1,87 @@
# This workflow will build a golang project and test cross-platform functionality
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Go Test

on:
push:
branches: [ "main" ]
branches: [main, 'release/**']
pull_request:
branches: [ "main", "v*" ]
branches: [main, 'v*']
workflow_dispatch:
workflow_call:

jobs:
permissions:
contents: read

test-cross-platform:
jobs:
native:
name: ${{ matrix.os }} / Go ${{ matrix.go }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
go-version: ['1.21', '1.22']
fail-fast: false
go: ['1.26.x', '1.27.x']
runs-on: ${{ matrix.os }}
env:
GOTOOLCHAIN: local
steps:
- uses: actions/checkout@v5

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}

- name: Cache Go modules
uses: actions/cache@v5
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-${{ matrix.go-version }}-

- name: Download dependencies
run: go mod download

- name: Run Tests with Coverage
shell: bash
run: go test -v -race -coverprofile=coverage.out -covermode=atomic ./...

- name: Upload coverage to Codecov
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.22'
uses: codecov/codecov-action@v5
with:
files: ./coverage.out
flags: unittests
name: codecov-umbrella

- name: Build for Current Platform
run: go build -v .

- name: Test Version Command
shell: bash
run: |
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
./conceal.exe version
else
./conceal version
fi

cross-compilation:
- uses: actions/checkout@v5
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
- name: Unit tests and race detector
run: go test -race -count=1 '-coverprofile=coverage.out' -covermode=atomic ./...
- name: Create isolated macOS test keychain
if: runner.os == 'macOS'
shell: bash
run: |
set -euo pipefail
password=$(uuidgen)
security create-keychain -p "$password" "$RUNNER_TEMP/conceal-test.keychain-db"
security set-keychain-settings -lut 3600 "$RUNNER_TEMP/conceal-test.keychain-db"
security unlock-keychain -p "$password" "$RUNNER_TEMP/conceal-test.keychain-db"
security default-keychain -s "$RUNNER_TEMP/conceal-test.keychain-db"
- name: Native credential store lifecycle
env:
CONCEAL_INTEGRATION: '1'
run: go test -count=1 -v ./pkg/conceal/keychain
- name: Remove macOS test keychain
if: always() && runner.os == 'macOS'
run: |
if [[ -f "$RUNNER_TEMP/conceal-test.keychain-db" ]]; then
security delete-keychain "$RUNNER_TEMP/conceal-test.keychain-db"
fi
- name: Build native CLI
run: go build -trimpath -o bin/ .
- name: CLI smoke test
shell: bash
run: |
set -euo pipefail
binary=./bin/conceal
if [[ "$RUNNER_OS" == Windows ]]; then binary=./bin/conceal.exe; fi
"$binary" version
"$binary" action example > example.json
"$binary" action validate example.json
"$binary" run --help
- uses: actions/upload-artifact@v4
with:
name: native-${{ runner.os }}-go-${{ matrix.go }}
path: |
bin/
coverage.out
if-no-files-found: error

cross-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'

- name: Cross Compile for Windows
run: |
GOOS=windows GOARCH=amd64 go build -o conceal-windows.exe .
ls -la conceal-windows.exe

- name: Cross Compile for macOS (syntax check only)
run: |
echo "Note: Full macOS build with CGO tested in macos-integration job"
echo "Cross-compilation test passed - actual macOS build requires native runner"

- name: Cross Compile for Linux
run: |
GOOS=linux GOARCH=amd64 go build -o conceal-linux .
ls -la conceal-linux

windows-integration:
runs-on: windows-latest
steps:
- uses: actions/checkout@v5

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'

- name: Build Windows Binary
run: go build -o conceal.exe .

- name: Test Basic Commands (Windows)
shell: pwsh
run: |
./conceal.exe version
./conceal.exe help
# Note: Cannot test actual credential operations in CI without user interaction

- name: Verify Windows-specific Code Compilation
run: go build -tags windows ./pkg/conceal/wincred/...

macos-integration:
runs-on: macos-latest
steps:
- uses: actions/checkout@v5

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'

- name: Build macOS Binary
run: go build -o conceal .

- name: Test Basic Commands (macOS)
run: |
./conceal version
./conceal help
# Note: Cannot test actual keychain operations in CI without user interaction

- name: Verify macOS-specific Code Compilation
run: go build -tags darwin ./pkg/conceal/keychain/...
- uses: actions/checkout@v5
- uses: actions/setup-go@v5
with:
go-version: '1.27.x'
- name: Windows and Linux release architectures
shell: bash
run: |
set -euo pipefail
for target in linux/386 linux/amd64 linux/arm64 windows/amd64 windows/arm64; do
os=${target%/*}
arch=${target#*/}
CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" go build -trimpath -o "bin/conceal-$os-$arch" .
done
Loading
Loading