Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.16.4 backports 2 #31479

Merged
merged 17 commits into from
Mar 1, 2023
Merged
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
8 changes: 7 additions & 1 deletion .github/ci-prerequisites.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@
# alpine 3.14 dd53f409bf0b 4 months ago 5.6MB
# alpine 3.15 c4fc93816858 4 months ago 5.58MB

time docker rmi node:14 node:16 node:18 buildpack-deps:buster buildpack-deps:bullseye
time docker rmi node:14 node:16 node:18 node:14-alpine node:16-alpine node:18-alpine buildpack-deps:buster buildpack-deps:bullseye
# That is 979M
time sudo rm -rf /usr/share/dotnet
# That is 1.7G
time sudo rm -rf /usr/share/swift
# Remove Android
time sudo rm -rf /usr/local/lib/android
# Remove Haskell
time sudo rm -rf /opt/ghc
# Remove pipx
time sudo rm -rf /opt/pipx
14 changes: 14 additions & 0 deletions .github/workflows/doc-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
- 'docs/src/main/asciidoc/**'
- '.github/workflows/doc-build.yml'
pull_request:
types: [opened, synchronize, reopened]
paths:
- 'docs/src/main/asciidoc/**'
- '.github/workflows/doc-build.yml'
Expand Down Expand Up @@ -58,3 +59,16 @@ jobs:
- name: Build Docs
run: |
./mvnw -e -B --settings .github/mvn-settings.xml clean package -pl docs
- name: Store PR id
run: echo ${{ github.event.number }} > pr-id.txt

- name: Persist documentation
uses: actions/upload-artifact@v3
with:
name: documentation
path: |
pr-id.txt
docs/
target/asciidoc/generated/config/
retention-days: 1
22 changes: 22 additions & 0 deletions .github/workflows/preview-teardown.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Surge.sh Preview Teardown

on:
pull_request_target:
types: [closed]

jobs:
preview-teardown:
runs-on: ubuntu-latest
steps:
- name: Teardown surge preview
id: deploy
run: npx surge teardown https://quarkus-io-pr-main-${{ steps.pr.outputs.id }}-preview.surge.sh --token ${{ secrets.SURGE_TOKEN }}
- name: Update PR status comment
uses: actions-cool/[email protected]
with:
token: ${{ secrets.GITHUB_TOKEN }}
body: |
🙈 The PR is closed and the preview is expired.
<!-- Sticky Pull Request Comment -->
body-include: '<!-- Sticky Pull Request Comment -->'
number: ${{ github.event.number }}
100 changes: 100 additions & 0 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: Surge.sh Preview

on:
workflow_run:
workflows: ["Quarkus Documentation CI"]
types:
- completed

jobs:
preview:
runs-on: ubuntu-latest
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
steps:
- name: Download PR Artifact
uses: dawidd6/action-download-artifact@v2
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
workflow_conclusion: success
name: documentation
path: documentation
- name: Store PR id as variable
id: pr
run: |
echo "id=$(<documentation/pr-id.txt)" >> $GITHUB_OUTPUT
rm -f pr-id.txt
- uses: actions/checkout@v3
with:
repository: quarkusio/quarkusio.github.io
path: quarkusio
- name: Sync documentation
shell: bash
run: |
chmod 755 ./documentation/docs/sync-web-site.sh
./documentation/docs/sync-web-site.sh main ../../quarkusio/
- name: Set up ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7 # can change this to 2.7 or whatever version you prefer
- name: Build Jekyll site
uses: limjh16/jekyll-action-ts@v2
with:
enable_cache: true
### Enables caching. Similar to https://github.com/actions/cache.
#
format_output: false
### Uses prettier https://prettier.io to format jekyll output HTML.
#
# prettier_opts: '{ "useTabs": true }'
### Sets prettier options (in JSON) to format output HTML. For example, output tabs over spaces.
### Possible options are outlined in https://prettier.io/docs/en/options.html
#
prettier_ignore: '*'
### Ignore paths for prettier to not format those html files.
### Useful if the file is exceptionally large, so formatting it takes a while.
### Also useful if HTML compression is enabled for that file / formatting messes it up.
#
# jekyll_src: sample_site
### If the jekyll website source is not in root, specify the directory. (in this case, sample_site)
### By default, this is not required as the action searches for a _config.yml automatically.
#
gem_src: quarkusio
### By default, this is not required as the action searches for a _config.yml automatically.
### However, if there are multiple Gemfiles, the action may not be able to determine which to use.
### In that case, specify the directory. (in this case, sample_site)
###
### If jekyll_src is set, the action would automatically choose the Gemfile in jekyll_src.
### In that case this input may not be needed as well.
#
# key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
# restore-keys: ${{ runner.os }}-gems-
### In cases where you want to specify the cache key, enable the above 2 inputs
### Follows the format here https://github.com/actions/cache
#
# custom_opts: '--future'
### If you need to specify any Jekyll build options, enable the above input
### Flags accepted can be found here https://jekyllrb.com/docs/configuration/options/#build-command-options
- name: Publishing to surge for preview
id: deploy
run: npx surge ./quarkusio/_site --domain https://quarkus-io-pr-main-${{ steps.pr.outputs.id }}-preview.surge.sh --token ${{ secrets.SURGE_TOKEN }}
- name: Update PR status comment on success
uses: actions-cool/[email protected]
with:
token: ${{ secrets.GITHUB_TOKEN }}
body: |
🎊 PR Preview ${{ github.sha }} has been successfully built and deployed to https://quarkus-io-pr-main-${{ steps.pr.outputs.id }}-preview.surge.sh/version/main/guides/
<img width="300" src="https://user-images.githubusercontent.com/507615/90250366-88233900-de6e-11ea-95a5-84f0762ffd39.png">
<!-- Sticky Pull Request Comment -->
body-include: '<!-- Sticky Pull Request Comment -->'
number: ${{ steps.pr.outputs.id }}
- name: Update PR status comment on failure
if: ${{ failure() }}
uses: actions-cool/[email protected]
with:
token: ${{ secrets.GITHUB_TOKEN }}
body: |
😭 Deploy PR Preview failed.
<img width="300" src="https://user-images.githubusercontent.com/507615/90250824-4e066700-de6f-11ea-8230-600ecc3d6a6b.png">
<!-- Sticky Pull Request Comment -->
body-include: '<!-- Sticky Pull Request Comment -->'
number: ${{ steps.pr.outputs.id }}
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,16 @@

import static io.quarkus.deployment.pkg.steps.LinuxIDUtil.getLinuxID;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.apache.commons.lang3.SystemUtils;
import org.jboss.logging.Logger;

import io.quarkus.deployment.OutputFilter;
import io.quarkus.deployment.pkg.NativeConfig;
import io.quarkus.deployment.util.ExecUtil;
import io.quarkus.deployment.util.FileUtil;
import io.quarkus.runtime.util.ContainerRuntimeUtil;

Expand All @@ -34,14 +23,16 @@ public NativeImageBuildLocalContainerRunner(NativeConfig nativeConfig, Path outp
super(nativeConfig, outputDir);
if (SystemUtils.IS_OS_LINUX) {
ArrayList<String> containerRuntimeArgs = new ArrayList<>(Arrays.asList(baseContainerRuntimeArgs));
if (isDockerRootless(containerRuntime)) {
if (containerRuntime == ContainerRuntimeUtil.ContainerRuntime.DOCKER
&& containerRuntime.isRootless()) {
Collections.addAll(containerRuntimeArgs, "--user", String.valueOf(0));
} else {
String uid = getLinuxID("-ur");
String gid = getLinuxID("-gr");
if (uid != null && gid != null && !uid.isEmpty() && !gid.isEmpty()) {
Collections.addAll(containerRuntimeArgs, "--user", uid + ":" + gid);
if (containerRuntime == ContainerRuntimeUtil.ContainerRuntime.PODMAN) {
if (containerRuntime == ContainerRuntimeUtil.ContainerRuntime.PODMAN
&& containerRuntime.isRootless()) {
// Needed to avoid AccessDeniedExceptions
containerRuntimeArgs.add("--userns=keep-id");
}
Expand All @@ -51,63 +42,6 @@ public NativeImageBuildLocalContainerRunner(NativeConfig nativeConfig, Path outp
}
}

private static boolean isDockerRootless(ContainerRuntimeUtil.ContainerRuntime containerRuntime) {
if (containerRuntime != ContainerRuntimeUtil.ContainerRuntime.DOCKER) {
return false;
}
String dockerEndpoint = fetchDockerEndpoint();
// docker socket?
String socketUriPrefix = "unix://";
if (dockerEndpoint == null || !dockerEndpoint.startsWith(socketUriPrefix)) {
return false;
}
String dockerSocket = dockerEndpoint.substring(socketUriPrefix.length());
String currentUid = getLinuxID("-ur");
if (currentUid == null || currentUid.isEmpty() || currentUid.equals(String.valueOf(0))) {
return false;
}

int socketOwnerUid;
try {
socketOwnerUid = (int) Files.getAttribute(Path.of(dockerSocket), "unix:uid", LinkOption.NOFOLLOW_LINKS);
} catch (IOException e) {
LOGGER.infof("Owner UID lookup on '%s' failed with '%s'", dockerSocket, e.getMessage());
return false;
}
return currentUid.equals(String.valueOf(socketOwnerUid));
}

private static String fetchDockerEndpoint() {
// DOCKER_HOST environment variable overrides the active context
String dockerHost = System.getenv("DOCKER_HOST");
if (dockerHost != null) {
return dockerHost;
}

OutputFilter outputFilter = new OutputFilter();
if (!ExecUtil.execWithTimeout(new File("."), outputFilter, Duration.ofMillis(3000),
"docker", "context", "ls", "--format",
"{{- if .Current -}} {{- .DockerEndpoint -}} {{- end -}}")) {
LOGGER.debug("Docker context lookup didn't succeed in time");
return null;
}

Set<String> endpoints = outputFilter.getOutput().lines()
.filter(Objects::nonNull)
.filter(Predicate.not(String::isBlank))
.collect(Collectors.toSet());
if (endpoints.size() == 1) {
return endpoints.stream().findFirst().orElse(null);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debugf("Found too many active Docker endpoints: [%s]",
endpoints.stream()
.map(endpoint -> String.format("'%s'", endpoint))
.collect(Collectors.joining(",")));
}
return null;
}

@Override
protected List<String> getContainerRuntimeBuildArgs() {
List<String> containerRuntimeArgs = super.getContainerRuntimeBuildArgs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ private boolean runUpxInContainer(NativeImageBuildItem nativeImage, NativeConfig
String gid = getLinuxID("-gr");
if (uid != null && gid != null && !uid.isEmpty() && !gid.isEmpty()) {
Collections.addAll(commandLine, "--user", uid + ":" + gid);
if (containerRuntime == ContainerRuntimeUtil.ContainerRuntime.PODMAN) {
if (containerRuntime == ContainerRuntimeUtil.ContainerRuntime.PODMAN
&& containerRuntime.isRootless()) {
// Needed to avoid AccessDeniedExceptions
commandLine.add("--userns=keep-id");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package io.quarkus.runtime.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.function.Predicate;

import org.jboss.logging.Logger;

Expand Down Expand Up @@ -59,15 +63,60 @@ private static String getVersionOutputFor(ContainerRuntime containerRuntime) {
}
}

private static boolean getRootlessStateFor(ContainerRuntime containerRuntime) {
Process rootlessProcess = null;
try {
ProcessBuilder pb = new ProcessBuilder(containerRuntime.getExecutableName(), "info")
.redirectErrorStream(true);
rootlessProcess = pb.start();
int exitCode = rootlessProcess.waitFor();
if (exitCode != 0) {
log.warnf("Command \"%s\" exited with error code %d. " +
"Rootless container runtime detection might not be reliable.",
containerRuntime.getExecutableName(), exitCode);
}
try (InputStream inputStream = rootlessProcess.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
Predicate<String> stringPredicate;
// Docker includes just "rootless" under SecurityOptions, while podman includes "rootless: <boolean>"
if (containerRuntime == ContainerRuntime.DOCKER) {
stringPredicate = line -> line.trim().equals("rootless");
} else {
stringPredicate = line -> line.trim().equals("rootless: true");
}
return bufferedReader.lines().anyMatch(stringPredicate);
}
} catch (IOException | InterruptedException e) {
// If an exception is thrown in the process, assume we are not running rootless (default docker installation)
log.debugf(e, "Failure to read info output from %s", containerRuntime.getExecutableName());
return false;
} finally {
if (rootlessProcess != null) {
rootlessProcess.destroy();
}
}
}

/**
* Supported Container runtimes
*/
public enum ContainerRuntime {
DOCKER,
PODMAN;

private final boolean rootless;

ContainerRuntime() {
this.rootless = getRootlessStateFor(this);
}

public String getExecutableName() {
return this.name().toLowerCase();
}

public boolean isRootless() {
return rootless;
}
}
}
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/qute-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ And must be used in a form of `{item_hasNext}` inside a `{#for}` section with th
{#for item in items}
{item_count}. {item.name} <1>
{#if item_hasNext}<br>{/if} <2>
{/each}
{/for}
----
<1> `item_count` represents one-based index.
<2> `<br>` is only rendered if the iteration has more elements.
Expand Down
Loading