Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
15 changes: 0 additions & 15 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,8 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Setup binary permissions
run: chmod a+x artifacts/pixi*

- name: Run integration tests
run: pixi run --locked test-slow
env:
PIXI_BIN_DIR: ${{ github.workspace }}/artifacts
BUILD_BACKENDS_BIN_DIR: ${{ github.workspace }}/artifacts

test-windows-x86_64:
timeout-minutes: 10
Expand Down Expand Up @@ -78,9 +72,6 @@ jobs:
- name: Run integration tests
run: pixi run --locked test-slow
working-directory: ${{ env.PIXI_WORKSPACE }}
env:
PIXI_BIN_DIR: ${{ env.PIXI_WORKSPACE }}/artifacts
BUILD_BACKENDS_BIN_DIR: ${{ env.PIXI_WORKSPACE }}/artifacts

test-macos-aarch64:
timeout-minutes: 10
Expand All @@ -100,11 +91,5 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Setup binary permissions
run: chmod a+x artifacts/pixi*

- name: Run integration tests
run: pixi run --locked test-slow
env:
PIXI_BIN_DIR: ${{ github.workspace }}/artifacts
BUILD_BACKENDS_BIN_DIR: ${{ github.workspace }}/artifacts
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ If you prefer to use local checkouts, create a `.env` file with the paths to you

```shell
PIXI_REPO="/path/to/pixi-repository"
BUILD_BACKENDS_REPO="/path/to/pixi-build-backends-repository"

PIXI_BIN_DIR="${PIXI_REPO}/target/pixi/release"
BUILD_BACKENDS_BIN_DIR="${BUILD_BACKENDS_REPO}/target/pixi/release"

BUILD_BACKENDS_REPO="/path/to/pixi-build-backends-repository"
```

Then build the binaries with:
Expand Down
2 changes: 1 addition & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[mypy]
strict = True
exclude = tests/data/pypi-indexes
exclude = tests/data/pypi-indexes|.*setup\.py
files = tests,scripts
50 changes: 44 additions & 6 deletions scripts/build-repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,28 @@ class PixiBuildError(Exception):
pass


class PixiChannelError(Exception):
"""Raised when creating the testsuite channel fails."""

pass


def run_command(
cmd: list[str], cwd: Path | None = None, capture_output: bool = True
cmd: list[str],
cwd: Path | None = None,
capture_output: bool = True,
env: dict[str, str] | None = None,
) -> tuple[int, str, str]:
"""Run a command and return exit code, stdout, and stderr."""
result = subprocess.run(cmd, cwd=cwd, capture_output=capture_output, text=True)
result = subprocess.run(cmd, cwd=cwd, capture_output=capture_output, text=True, env=env)
return result.returncode, result.stdout, result.stderr


def executable_name(base: str) -> str:
"""Return the platform specific executable name."""
return f"{base}.exe" if sys.platform.startswith("win") else base


def is_git_worktree(path: Path) -> bool:
"""Check if the given path is inside a git work tree (repo or worktree)."""
if not path.exists() or not path.is_dir():
Expand Down Expand Up @@ -89,6 +103,30 @@ def build_executables(repo_path: Path) -> None:
raise PixiBuildError(error_msg)


def create_channel(repo_path: Path, project_root: Path) -> None:
"""Create the local testsuite channel and move it into this repository."""
channel_source = repo_path / "artifacts-channel"

print("📦 Creating channel")
returncode, stdout, stderr = run_command(["pixi", "run", "create-channel"], cwd=repo_path)

if returncode != 0:
error_msg = "Failed to create testsuite channel"
if stderr:
error_msg += f": {stderr}"
if stdout:
error_msg += f" (Output: {stdout})"
raise PixiChannelError(error_msg)

if not channel_source.exists():
raise PixiChannelError(
f"Expected channel directory '{channel_source}' was not created. "
"Verify that 'pixi run create-channel' completed successfully."
)

print("✅ Testsuite channel ready at source repo")


def process_repository(repo_path: Path, repo_name: str) -> None:
"""Process a single repository: verify, pull if on main, and build."""
print(f"\n{'=' * 60}")
Expand All @@ -112,14 +150,12 @@ def process_repository(repo_path: Path, repo_name: str) -> None:
else:
print("⚠️ Could not determine current branch")

# Run pixi build
build_executables(repo_path)


def main() -> None:
"""Main function to process repositories."""
# Load environment variables from .env file
env_file = Path(__file__).parent.parent / ".env"
project_root = Path(__file__).parent.parent
env_file = project_root / ".env"
if env_file.exists():
load_dotenv(env_file, override=True)
print(f"✅ Loaded environment variables from {env_file}")
Expand Down Expand Up @@ -150,12 +186,14 @@ def main() -> None:

try:
process_repository(pixi_repo_path, "PIXI_REPO")
build_executables(pixi_repo_path)
except Exception as e:
print(f"❌ Error processing PIXI_REPO: {e}")
success = False

try:
process_repository(build_backends_repo_path, "BUILD_BACKENDS_REPO")
create_channel(build_backends_repo_path, project_root)
except Exception as e:
print(f"❌ Error processing BUILD_BACKENDS_REPO: {e}")
success = False
Expand Down
53 changes: 16 additions & 37 deletions scripts/download-artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,48 +139,27 @@ def download_and_extract_artifact(
console.print(f"[green]Successfully downloaded pixi binary to: {final_path}")

elif repo == "prefix-dev/pixi-build-backends":
# Extract all pixi-build-* executables
backend_executables = []
is_windows = sys.platform.startswith("win")

# Find the pixi binary
is_channel = None
for file_name in file_list:
base_name = Path(file_name).name
if base_name.startswith("pixi-build-"):
# On Windows, expect .exe extension; on others, no extension
if is_windows and base_name.endswith(".exe"):
backend_executables.append(file_name)
elif not is_windows and not base_name.endswith(".exe") and "." not in base_name:
backend_executables.append(file_name)

if not backend_executables:
console.print("[red]Could not find any pixi-build-* executables in archive")
raise FileNotFoundError(
f"Could not find any pixi-build-* executables in archive. Archive contents: {file_list}"
)

console.print(f"[blue]Found {len(backend_executables)} backend executable(s)")

# Extract all executables
for executable in backend_executables:
final_path = output_dir / Path(executable).name
if final_path.exists():
if final_path.is_dir():
shutil.rmtree(final_path)
else:
final_path.unlink()

zip_ref.extract(executable, output_dir)
extracted_path = output_dir / executable
if file_name.endswith("repodata.json"):
is_channel = True
break

if extracted_path != final_path:
extracted_path.rename(final_path)
if not is_channel:
console.print("[red]Could not locate a channel directory inside the artifact.")
raise FileNotFoundError("Could not locate a channel directory inside the artifact.")

# Make executable on Unix systems
if not sys.platform.startswith("win"):
final_path.chmod(0o755)
console.print("[blue]Detected backend channel artifact")
final_channel_path = output_dir / "pixi-build-backends"
if final_channel_path.exists():
console.print(f"[yellow]Removing existing channel at {final_channel_path}")
shutil.rmtree(final_channel_path)

console.print(f"[green]Extracted executable: {final_path}")
final_channel_path.parent.mkdir(parents=True, exist_ok=True)
zip_ref.extractall(final_channel_path)

console.print(f"[green]Channel is ready at: {final_channel_path}")
else:
raise ValueError(f"Unsupported repository: {repo}")

Expand Down
Loading
Loading