diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f15441a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..78fb2b9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Ensure consistent line endings for shell scripts and text files +* text=auto eol=lf + +# Shell scripts must always use LF +*.sh text eol=lf + +# Manifests and config +*.yml text eol=lf +*.yaml text eol=lf +*.json text eol=lf +*.xml text eol=lf +*.desktop text eol=lf +*.ini text eol=lf +*.flatpakrepo text eol=lf + +# Documentation +*.md text eol=lf + +# Binary β€” do not diff or convert +*.png binary +*.flatpak binary +*.gpg binary diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..dfb90b7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/flatter.yml b/.github/workflows/flatter.yml new file mode 100644 index 0000000..54bad76 --- /dev/null +++ b/.github/workflows/flatter.yml @@ -0,0 +1,70 @@ +name: Flatter (signed) + +on: + push: + workflow_dispatch: + schedule: + # Rebuild weekly to catch upstream changes + - cron: "0 2 * * 0" + +jobs: + flatter: + name: Build Flatpak Packages + runs-on: ubuntu-latest + permissions: + contents: read + actions: write + container: + image: ghcr.io/andyholmes/flatter/freedesktop:25.08 + options: --privileged + + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Setup GPG + # Skip GPG signing for pull requests (requires secrets from repo owner) + if: ${{ github.triggering_actor == github.repository_owner && github.event_name != 'pull_request' }} + id: gpg + uses: crazy-max/ghaction-import-gpg@v7 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + + - name: Install Flatpak Dependencies + # The freedesktop Flatter image ships the Platform/Sdk but not the + # Electron BaseApp our manifest needs (`base:`, providing zypak). + # flatpak-builder doesn't auto-install it - unlike a local + # `--install-deps-from=flathub` build, Flatter's own flatpak-builder + # invocation has no such flag, so it must already be present before + # "Build Packages" runs. + run: | + flatpak install --noninteractive flathub \ + org.electronjs.Electron2.BaseApp//25.08 + + - name: Build Packages + uses: andyholmes/flatter@main + with: + files: | + com.visualstudio.code.yaml + gpg-sign: ${{ steps.gpg.outputs.fingerprint }} + upload-pages-artifact: true + upload-pages-includes: | + index.html + README.md + + deploy: + name: Deploy + runs-on: ubuntu-latest + needs: flatter + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 diff --git a/.github/workflows/update-checker.yml b/.github/workflows/update-checker.yml new file mode 100644 index 0000000..57bb202 --- /dev/null +++ b/.github/workflows/update-checker.yml @@ -0,0 +1,34 @@ +name: Update Checker + +on: + schedule: + - cron: "0 6 * * *" # daily at 06:00 UTC + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + check: + name: Check com.visualstudio.code.yaml + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Check and update com.visualstudio.code.yaml + uses: docker://ghcr.io/flathub/flatpak-external-data-checker:latest + env: + GIT_AUTHOR_NAME: Flatpak External Data Checker + GIT_COMMITTER_NAME: Flatpak External Data Checker + # Sets commit author to github-actions[bot] + GIT_AUTHOR_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: --update --never-fork com.visualstudio.code.yaml diff --git a/.gitignore b/.gitignore index c00df13..69404e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,18 @@ +.DS_Store +.flatpak-builder/ *.deb +*.flatpak +*.key +*.swo +*.swp +*~ +build-dir/ +dist/repo +flatpak_app/ +flatter-keyring/ +node_modules +oci-bundle/ +package-lock.json +private.key +repo/ +Thumbs.db diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cc3223a --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +MIT License + +Copyright (c) 2026 FranΓ§ois M. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- + +This license covers the packaging metadata in this repository only. Visual +Studio Code itself is proprietary software by Microsoft Corporation, +downloaded from Microsoft's servers at install time; see +https://code.visualstudio.com/license. diff --git a/README.md b/README.md index c8c8fd2..ca4f1c3 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,102 @@ # Visual Studio Code Flatpak -🚨 Warning: This is an unofficial Flatpak build of Visual Studio Code, generated from the official Microsoft-built .deb packages [here](https://github.com/flathub/com.visualstudio.code/blob/master/com.visualstudio.code.yaml#L103). +🚨 Warning: This is an unofficial Flatpak build of Visual Studio Code, generated from the official Microsoft-built .deb packages [here](https://github.com/francoism90/com.visualstudio.code/blob/master/com.visualstudio.code.yaml#L103). ## Table of Contents +- [Quick Start](#quick-start) + - [Build](#build) + - [Nested-sandbox install error](#nested-sandbox-install-error) + - [Signing](#signing) - [Usage](#usage) - [Execute commands in the host system.](#execute-commands-in-the-host-system) - [Use host shell in the integrated terminal.](#use-host-shell-in-the-integrated-terminal) - [Support for language extension.](#support-for-language-extension) - [Support](#support) +## Quick Start + +Add the remote repository: + +```bash +flatpak remote-add --user --if-not-exists francoism90-vscode https://francoism90.github.io/com.visualstudio.code/index.flatpakrepo +``` + +Update the repository: + +```bash +flatpak update +``` + +Install the app: + +```bash +flatpak install francoism90-vscode com.visualstudio.code +``` + +> Note: the app will automatically update when you run `flatpak update`. + +```bash +flatpak run com.visualstudio.code +``` + +### Build + +It is possible to build the app yourself instead of using the prebuilt, signed +repo above. + +```bash +git clone https://github.com/francoism90/com.visualstudio.code.git +cd com.visualstudio.code +./build.sh +flatpak run com.visualstudio.code +``` + +`build.sh` adds the Flathub remote (user), builds to a local repo, then +installs from that repo with the host's own `flatpak` binary (see +"Nested-sandbox install error" below for why it's split into two steps). + +To build manually: + +```bash +flatpak run org.flatpak.Builder --user --install-deps-from=flathub --force-clean --repo=repo \ + build-dir com.visualstudio.code.yaml +flatpak --user remote-add --if-not-exists com.visualstudio.code-local ./repo --no-gpg-verify +flatpak --user install --noninteractive com.visualstudio.code-local com.visualstudio.code +``` + +#### Nested-sandbox install error + +If `flatpak-builder` on your `$PATH` is itself a Flatpak (`org.flatpak.Builder`, +e.g. on immutable/hardened distros without a native package), running it with +`--install` directly can fail with: + +``` +bwrap: No permissions to create a new namespace, likely because the kernel +does not allow non-privileged user namespaces. +Error: Failed to install com.visualstudio.code: ... +``` + +That's `org.flatpak.Builder`'s own sandbox trying to nest another `bwrap` +sandbox for `flatpak install`, which some kernels/hardening policies block +regardless of user-namespace permissions otherwise being fine. Building to a +local repo and installing with the *host's* `flatpak` binary β€” as `build.sh` +and the manual steps above do β€” sidesteps it, since that install then only +needs one level of sandboxing, not two. + +### Signing + +The signed repo published to GitHub Pages by `.github/workflows/flatter.yml` +needs a GPG key in the `GPG_PRIVATE_KEY` (and optionally `GPG_PASSPHRASE`) +repo secrets. Generate one with: + +```bash +bin/create-keys "Your Name" "you@example.com" +``` + +This prints the values to add as repo secrets. Delete `private.key` and the +`flatter-keyring/` directory afterwards β€” never commit them. + ## Usage Most functionality works out of the box, though please note that flatpak runs in an isolated environment and some work is necessary to enable those features. @@ -89,10 +176,20 @@ $ flatpak install flathub org.freedesktop.Sdk.Extension.golang $ FLATPAK_ENABLE_SDK_EXT=dotnet,golang flatpak run com.visualstudio.code ``` +**Container support (Podman)** + +To use Podman as a container runtime inside the sandbox (e.g. for Dev Containers), install the [`org.freedesktop.Sdk.Extension.podman`](https://github.com/francoism90/org.freedesktop.Sdk.Extension.podman) SDK extension from its own repo (not on Flathub β€” see that repo for why) and enable it the same way: + +``` +$ flatpak remote-add --if-not-exists francoism90-podman https://francoism90.github.io/org.freedesktop.Sdk.Extension.podman/index.flatpakrepo +$ flatpak install francoism90-podman org.freedesktop.Sdk.Extension.podman +$ FLATPAK_ENABLE_SDK_EXT=podman flatpak run com.visualstudio.code +``` + **Finding other SDK** `flatpak search ` ## Support -Please open issues under: https://github.com/flathub/com.visualstudio.code/issues +Please open issues under: https://github.com/francoism90/com.visualstudio.code/issues diff --git a/bin/create-keys b/bin/create-keys new file mode 100755 index 0000000..2f79068 --- /dev/null +++ b/bin/create-keys @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# create-keys β€” generate a GPG signing key for your Flatpak repository and +# print the values you need to add as GitHub repository secrets. +# +# Usage: bin/create-keys [NAME] [EMAIL] +# NAME Human-readable key name (default: "Flatpak Repo") +# EMAIL Key email address (default: "flatpak@example.com") +# +# The private key is written to private.key and the keyring is stored in +# flatter-keyring/ (both in the current directory). +# Add private.key contents to the GPG_PRIVATE_KEY GitHub secret, then +# delete both private.key and the flatter-keyring/ directory. + +set -euo pipefail + +NAME="${1:-Flatpak Repo}" +EMAIL="${2:-flatpak@example.com}" +KEYHOME="./flatter-keyring" + +# Create isolated GPG keyring directory +mkdir -p "$KEYHOME" +chmod 700 "$KEYHOME" + +echo "Generating GPG key for '${NAME} <${EMAIL}>'..." + +gpg --homedir "$KEYHOME" --batch --gen-key < private.key +FINGERPRINT=$(gpg --homedir "$KEYHOME" --with-colons --fingerprint "${KEY_ID}" | awk -F: '/^fpr:/ {print $10; exit}') + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo " GitHub repository secrets" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo " GPG key id: ${KEY_ID}" +echo " GPG fingerprint: ${FINGERPRINT}" +echo "" +echo " Secret: GPG_PRIVATE_KEY" +echo " Value: use the full ASCII-armored private key below" +echo "" +cat private.key +echo "" +echo " Optional secret: GPG_PASSPHRASE" +echo " Value: only needed if your key is passphrase protected" +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo "⚠ Delete private.key and the keyring directory after uploading:" +echo " rm -f private.key && rm -rf \"$KEYHOME\"" +echo " Never commit these files to the repository." +echo "" diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..4594ea0 --- /dev/null +++ b/build.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Build and install the Visual Studio Code Flatpak (user install). +set -euo pipefail +cd "$(dirname "$0")" + +MANIFEST="com.visualstudio.code.yaml" +APP_ID="com.visualstudio.code" + +# The runtime, SDK and Electron BaseApp come from Flathub. --install-deps-from +# reads their exact versions from the manifest, so they can never drift from it. +flatpak --user remote-add --if-not-exists flathub \ + https://dl.flathub.org/repo/flathub.flatpakrepo + +if command -v flatpak-builder >/dev/null 2>&1; then + fb() { flatpak-builder "$@"; } +elif flatpak info --user org.flatpak.Builder >/dev/null 2>&1 || flatpak info org.flatpak.Builder >/dev/null 2>&1; then + fb() { flatpak run org.flatpak.Builder "$@"; } +else + echo "Installing org.flatpak.Builder from Flathub..." + flatpak --user install --noninteractive flathub org.flatpak.Builder + fb() { flatpak run org.flatpak.Builder "$@"; } +fi + +# Build to a local repo rather than installing directly with `fb --install`. +# On hosts that restrict nested user namespaces (e.g. hardened/atomic distros), +# org.flatpak.Builder β€” itself a sandboxed Flatpak app β€” cannot spawn the bwrap +# instance that `flatpak install` needs, and fails with "bwrap: No permissions +# to create a new namespace". Installing separately with the host's own +# `flatpak` binary avoids that nesting and works everywhere. +fb --user --install-deps-from=flathub --force-clean --repo=repo build-dir "$MANIFEST" + +flatpak --user remote-add --if-not-exists "${APP_ID}-local" ./repo --no-gpg-verify +flatpak --user install --noninteractive "${APP_ID}-local" "$APP_ID" + +echo +echo "Installed. Launch with: flatpak run $APP_ID" diff --git a/com.visualstudio.code.yaml b/com.visualstudio.code.yaml index 297561a..422feb9 100644 --- a/com.visualstudio.code.yaml +++ b/com.visualstudio.code.yaml @@ -59,11 +59,9 @@ modules: - install -Dm644 flatpak-warning.txt -t /app/share/vscode - install -D apply_extra -t /app/bin - cp /usr/bin/ar /app/bin - - ARCH_TRIPLE=$(gcc --print-multiarch) && cp /usr/lib/${ARCH_TRIPLE}/libbfd-*.so - /app/lib - - ARCH_TRIPLE=$(gcc --print-multiarch) && cp /usr/lib/${ARCH_TRIPLE}/libsframe* - /app/lib - - ARCH_TRIPLE=$(gcc --print-multiarch) && ln -s /usr/lib/${ARCH_TRIPLE}/libtinfo.so/app/lib/libtinfo.so.5 + - ARCH_TRIPLE=$(gcc --print-multiarch) && cp /usr/lib/${ARCH_TRIPLE}/libbfd-*.so /app/lib + - ARCH_TRIPLE=$(gcc --print-multiarch) && cp /usr/lib/${ARCH_TRIPLE}/libsframe* /app/lib + - ARCH_TRIPLE=$(gcc --print-multiarch) && ln -s /usr/lib/${ARCH_TRIPLE}/libtinfo.so /app/lib/libtinfo.so.5 - mkdir /app/tools sources: - type: script