Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
"node",
"playwright-deps",
"python",
"rust",
"sonar-scanner-cli",
"system-packages",
"timezone",
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Below is a list with included features, click on the link for more details.
| [node](./features/src/node/README.md) | Installs Node.js. |
| [playwright-deps](./features/src/playwright-deps/README.md) | Installs all dependencies required to run Playwright. |
| [python](./features/src/python/README.md) | Installs Python. |
| [rust](./features/src/rust/README.md) | A package which installs Rust. |
Comment thread
durdekm marked this conversation as resolved.
Outdated
| [sonar-scanner-cli](./features/src/sonar-scanner-cli/README.md) | Installs the SonarScanner CLI. |
| [system-packages](./features/src/system-packages/README.md) | Install arbitrary system packages using the system package manager. |
| [timezone](./features/src/timezone/README.md) | Allows setting the timezone. |
Expand Down
5 changes: 5 additions & 0 deletions build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ func init() {
gotaskr.Task("Feature:python:Test", func() error { return testFeature("python") })
gotaskr.Task("Feature:python:Publish", func() error { return publishFeature("python") })

////////// rust
gotaskr.Task("Feature:rust:Package", func() error { return packageFeature("rust") })
gotaskr.Task("Feature:rust:Test", func() error { return testFeature("rust") })
gotaskr.Task("Feature:rust:Publish", func() error { return publishFeature("rust") })

////////// sonar-scanner-cli
gotaskr.Task("Feature:sonar-scanner-cli:Package", func() error { return packageFeature("sonar-scanner-cli") })
gotaskr.Task("Feature:sonar-scanner-cli:Test", func() error { return testFeature("sonar-scanner-cli") })
Expand Down
10 changes: 10 additions & 0 deletions features/src/rust/NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## Notes

### System Compatibility

Debian, Ubuntu

### Accessed Urls

Needs access to the following URL for downloading and resolving:
* https://static.rust-lang.org
47 changes: 47 additions & 0 deletions features/src/rust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Rust (rust)

A package which installs Rust.
Comment thread
durdekm marked this conversation as resolved.
Outdated

## Example Usage

```json
"features": {
"ghcr.io/postfinance/devcontainer-features/rust:0.1.0": {
"version": "latest",
"rustupVersion": "latest",
"profile": "minimal",
"components": "rustfmt,rust-analyzer,rust-src,clippy",
"enableWindowsTarget": false
}
}
```

## Options

| Option | Description | Type | Default Value | Proposals |
|-----|-----|-----|-----|-----|
| version | The version of Rust to install. | string | latest | latest, 1.76 |
Comment thread
durdekm marked this conversation as resolved.
Outdated
| rustupVersion | The version of rustup to install. | string | latest | latest, 1.27.1 |
| profile | The rustup profile to install. | string | minimal | minimal, default, complete |
| components | A comma separated list with components that should be installed. | string | rustfmt,rust-analyzer,rust-src,clippy | , rustfmt,rust-analyzer, rls,rust-analysis |
| enableWindowsTarget | A flag to indicate if the Windows target (and needed tools) should be installed. | boolean | false | true, false |

## Customizations

### VS Code Extensions

- `vadimcn.vscode-lldb`
- `rust-lang.rust-analyzer`
- `tamasfe.even-better-toml`
- `serayuzgur.crates`

## Notes

### System Compatibility

Debian, Ubuntu

### Accessed Urls

Needs access to the following URL for downloading and resolving:
* https://static.rust-lang.org
66 changes: 66 additions & 0 deletions features/src/rust/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"id": "rust",
"version": "0.1.0",
"name": "Rust",
"description": "A package which installs Rust.",
"options": {
"version": {
"type": "string",
"proposals": [
"latest",
"1.76"
Comment thread
durdekm marked this conversation as resolved.
Outdated
],
"default": "latest",
"description": "The version of Rust to install."
},
"rustupVersion": {
"type": "string",
"proposals": [
"latest",
"1.27.1"
],
"default": "latest",
"description": "The version of rustup to install."
},
"profile": {
"type": "string",
"proposals": [
"minimal",
"default",
"complete"
],
"default": "minimal",
"description": "The rustup profile to install."
},
"components": {
"type": "string",
"proposals": [
"",
"rustfmt,rust-analyzer",
"rls,rust-analysis"
],
"default": "rustfmt,rust-analyzer,rust-src,clippy",
"description": "A comma separated list with components that should be installed."
},
"enableWindowsTarget": {
"type": "boolean",
"default": false,
"description": "A flag to indicate if the Windows target (and needed tools) should be installed."
}
},
"customizations": {
"vscode": {
"extensions": [
"vadimcn.vscode-lldb",
"rust-lang.rust-analyzer",
"tamasfe.even-better-toml",
"serayuzgur.crates"
]
}
},
"containerEnv": {
"CARGO_HOME": "/usr/local/cargo",
"RUSTUP_HOME": "/usr/local/rustup",
"PATH": "/usr/local/cargo/bin:${PATH}"
}
}
8 changes: 8 additions & 0 deletions features/src/rust/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
. ./functions.sh

"./installer_$(detect_arch)" \
-version="${VERSION:-"latest"}" \
-rustupVersion="${RUSTUPVERSION:-"latest"}" \
-profile="${PROFILE:-"minimal"}" \
-components="${COMPONENTS:-"rustfmt,rust-analyzer,rust-src,clippy"}" \
-enableWindowsTarget="${ENABLEWINDOWSTARGET:-"false"}"
183 changes: 183 additions & 0 deletions features/src/rust/installer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package main

import (
"builder/installer"
"flag"
"fmt"
"os"
"regexp"
"strings"

"github.com/roemer/gotaskr/execr"
"github.com/roemer/gover"
)

//////////
// Configuration
//////////

// Regex with 2-3 digits like 1.0 or 1.79.0
var threeDigitRegex *regexp.Regexp = regexp.MustCompile(`^?(\d+)\.(\d+)(?:\.(\d+))?$`)

// Full Regex versioning, like 1.0.0-alpha.2
var semVerRegex *regexp.Regexp = regexp.MustCompile(`^?(\d+)\.(\d+)(?:\.(\d+))?(?:-([a-z]+)(?:\.?(\d+))?)?$`)

//////////
// Main
//////////

func main() {
if err := runMain(); err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
}

func runMain() error {
// Handle the flags
version := flag.String("version", "lts", "")
Comment thread
durdekm marked this conversation as resolved.
rustupVersion := flag.String("rustupVersion", "latest", "")
profile := flag.String("profile", "minimal", "")
components := flag.String("components", "rustfmt,rust-analyzer,rust-src,clippy", "")
enableWindowsTarget := flag.Bool("enableWindowsTarget", false, "")
flag.Parse()

// Create and process the feature
feature := installer.NewFeature("PF Rust", true,
Comment thread
durdekm marked this conversation as resolved.
Outdated
&rustupComponent{
ComponentBase: installer.NewComponentBase("rustup", *rustupVersion),
profile: *profile,
},
&rustComponent{
ComponentBase: installer.NewComponentBase("rust", *version),
components: *components,
profile: *profile,
},
&buildEssentialComponent{
ComponentBase: installer.NewComponentBase("build-essential", installer.VERSION_SYSTEM_DEFAULT),
},
)
// Optional component
if *enableWindowsTarget {
feature.AddComponents(&windowsTargetComponent{
ComponentBase: installer.NewComponentBase("windows-target", installer.VERSION_IRRELEVANT),
})
}
// Last component
feature.AddComponents(&permissionsComponent{
ComponentBase: installer.NewComponentBase("permissions", installer.VERSION_IRRELEVANT),
})
return feature.Process()
}

//////////
// Implementation
//////////

type rustupComponent struct {
*installer.ComponentBase
profile string
}

func (c *rustupComponent) GetAllVersions() ([]*gover.Version, error) {
allTags, err := installer.Tools.GitHub.GetTags("rust-lang", "rustup")
if err != nil {
return nil, err
}
return installer.Tools.Versioning.ParseVersionsFromList(allTags, threeDigitRegex, true)
}

func (c *rustupComponent) InstallVersion(version *gover.Version) error {
// Download the file
archPart, err := installer.Tools.System.MapArchitecture(map[string]string{
installer.AMD64: "x86_64",
installer.ARM64: "aarch64",
})
if err != nil {
return err
}
fileName := "rustup-init"
downloadUrl := fmt.Sprintf("https://static.rust-lang.org/rustup/archive/%s/%s-unknown-linux-gnu/rustup-init", version.Raw, archPart)
if err := installer.Tools.Download.ToFile(downloadUrl, fileName, "Rustup-Init"); err != nil {
return err
}
// Install it
if err := os.Chmod(fileName, os.ModePerm); err != nil {
return err
}
if err := execr.Run(true, "./"+fileName, "-y", "--default-toolchain", "none", "--no-modify-path", "--profile", c.profile); err != nil {
return err
}
// Cleanup
if err := os.Remove(fileName); err != nil {
return err
}
return nil
}

type rustComponent struct {
*installer.ComponentBase
profile string
components string
}

func (c *rustComponent) GetAllVersions() ([]*gover.Version, error) {
allTags, err := installer.Tools.GitHub.GetTags("rust-lang", "rust")
if err != nil {
return nil, err
}
return installer.Tools.Versioning.ParseVersionsFromList(allTags, semVerRegex, true)
}

func (c *rustComponent) InstallVersion(version *gover.Version) error {
// Install it
if err := execr.Run(true, "rustup", "toolchain", "install", "--profile", c.profile, "--no-self-update", version.Raw); err != nil {
return err
}
// Installing the components
fmt.Printf("Installing components: %s\n", c.components)
args := []string{
"component",
"add",
}
for _, component := range strings.Split(c.components, ",") {
trimmed := strings.TrimSpace(component)
if trimmed != "" {
args = append(args, trimmed)
}
}
if err := execr.Run(true, "rustup", args...); err != nil {
return err
}
return nil
}

type buildEssentialComponent struct {
*installer.ComponentBase
}

func (c *buildEssentialComponent) InstallVersion(version *gover.Version) error {
return installer.Tools.System.InstallPackages("build-essential")
}

type windowsTargetComponent struct {
*installer.ComponentBase
}

func (c *windowsTargetComponent) InstallVersion(version *gover.Version) error {
if err := execr.Run(true, "rustup", "target", "add", "x86_64-pc-windows-gnu"); err != nil {
return err
}
if err := installer.Tools.System.InstallPackages("mingw-w64"); err != nil {
return err
}
return nil
}

type permissionsComponent struct {
*installer.ComponentBase
}

func (c *permissionsComponent) InstallVersion(version *gover.Version) error {
return execr.Run(true, "chmod", "-R", "777", os.Getenv("RUSTUP_HOME"), os.Getenv("CARGO_HOME"))
}
9 changes: 9 additions & 0 deletions features/test/rust/install-with-windows-target.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash
set -e

[[ -f "$(dirname "$0")/../functions.sh" ]] && source "$(dirname "$0")/../functions.sh"
[[ -f "$(dirname "$0")/functions.sh" ]] && source "$(dirname "$0")/functions.sh"

check_version "$(rustup --version 2>/dev/null)" "rustup 1.27.1 (54dd3d00f 2024-04-24)"
check_version "$(rustc --version)" "rustc 1.76.0 (07dca489a 2024-02-04)"
check_version "$(rustup target list --installed)" $'x86_64-pc-windows-gnu\nx86_64-unknown-linux-gnu'
9 changes: 9 additions & 0 deletions features/test/rust/install-without-windows-target.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash
set -e

[[ -f "$(dirname "$0")/../functions.sh" ]] && source "$(dirname "$0")/../functions.sh"
[[ -f "$(dirname "$0")/functions.sh" ]] && source "$(dirname "$0")/functions.sh"

check_version "$(rustup --version 2>/dev/null)" "rustup 1.27.1 (54dd3d00f 2024-04-24)"
check_version "$(rustc --version)" "rustc 1.76.0 (07dca489a 2024-02-04)"
check_version "$(rustup target list --installed)" $'x86_64-unknown-linux-gnu'
Loading
Loading