profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/CRogers/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
Callum Rogers CRogers @palantir London, United Kingdom

CRogers/baconsnake 7

The classic game snake, built in typescript

CRogers/AMDOverdriveControlled 5

Removing "safety" restrictions from popular overclocking tool

CRogers/coml 3

COffescript Markup Language. Like haml but written entirely in valid coffeescript.

CRogers/fay-typescript-def 3

An automatic typescript IDL to fay FFI compiler

CRogers/CarGC 2

A conservative C garbage collector

CRogers/EmptyDllMain 2

A library you can link again with if no other object files have a DllMain

CRogers/bananasnake 1

The classic game snake, built in Haskell

CRogers/binders 1

Playing around with http://www.cse.chalmers.se/~emax/documents/axelsson2013using.pdf

CRogers/blog 1

My musings.

PullRequestReviewEvent

Pull request review commentpalantir/witchcraft-java-logging

Formatted request log lines include parameters

             + "\"traceId\":\"ba3200b6eb01999a\",\"unsafeParams\":{\"path\":\"/api/sleep/10\","             + "\"millis\":\"10\"}}";     private static final String REQUEST_FORMATTED =-            "[2019-05-24T16:40:36.703Z] \"GET /api/sleep/10 HTTP/1.1\" " + "503 78 1935";+            "[2019-05-24T16:40:36.703Z] \"GET /api/sleep/10 HTTP/1.1\" 503 78 1935 μs (host: localhost:8443, "+                    + "connection: Keep-Alive, accept-encoding: gzip, user-agent: okhttp/3.13.1)";

Good point, we can filter there if we need to.

carterkozak

comment created time in 5 days

Pull request review commentpalantir/witchcraft-java-logging

Formatted request log lines include parameters

 void formats_correctly() {                 .params("param", "value")                 .build()); -        assertThat(formatted).isEqualTo("[2019-12-25T01:02:03Z] \"GET /some/path/value http\" 203 40 99");+        assertThat(formatted).isEqualTo("[2019-12-25T01:02:03Z] \"GET /some/path/value http\" 203 40 99 μs");

I would actually like that as I can never remember which of the last two refers to what

carterkozak

comment created time in 5 days

PullRequestReviewEvent

Pull request review commentpalantir/witchcraft-java-logging

Formatted request log lines include parameters

             + "\"traceId\":\"ba3200b6eb01999a\",\"unsafeParams\":{\"path\":\"/api/sleep/10\","             + "\"millis\":\"10\"}}";     private static final String REQUEST_FORMATTED =-            "[2019-05-24T16:40:36.703Z] \"GET /api/sleep/10 HTTP/1.1\" " + "503 78 1935";+            "[2019-05-24T16:40:36.703Z] \"GET /api/sleep/10 HTTP/1.1\" 503 78 1935 μs (host: localhost:8443, "+                    + "connection: Keep-Alive, accept-encoding: gzip, user-agent: okhttp/3.13.1)";

I wonder if this is going to be very spammy? I can see value of the host/user agent as you an see where the request came from (including in dev-env tests), but do we think connection/other parameters are important for daily debugging use?

carterkozak

comment created time in 5 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentpalantir/witchcraft-java-logging

Formatted request log lines include parameters

 void formats_correctly() {                 .params("param", "value")                 .build()); -        assertThat(formatted).isEqualTo("[2019-12-25T01:02:03Z] \"GET /some/path/value http\" 203 40 99");+        assertThat(formatted).isEqualTo("[2019-12-25T01:02:03Z] \"GET /some/path/value http\" 203 40 99 μs");

It might be nicer to put the μs right next to the duration like 99μs - otherwise I think that the other numbers might be other durations.

carterkozak

comment created time in 5 days

PullRequestReviewEvent

Pull request review commentpalantir/gradle-baseline

Configure tests to run concurrently

 private static void enableJunit5ForTestTask(Test task) {          // https://junit.org/junit5/docs/snapshot/user-guide/#writing-tests-parallel-execution         task.systemProperty("junit.jupiter.execution.parallel.enabled", "true");--        // Computes the desired parallelism based on the number of available processors/cores-        task.systemProperty("junit.jupiter.execution.parallel.config.strategy", "dynamic");

Chiming in that we intentionally did not make tests run in parallel by default as people's repos have tests which in general do not allow this, as they depend on state shared between tests, and our big fear was that people's tests would start flaking and they would not know why (as concurrency issues are hard to debug). People can opt in manually per test using @Execution(ExecutionMode.CONCURRENT) which also makes it obvious the tests are running in parallel.

pkoenig10

comment created time in 8 days

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentpalantir/conjure-typescript

Publish distribution to maven-central

:+1:

fawind

comment created time in 11 days

Pull request review commentpalantir/conjure-typescript

Publish distribution to maven-central

+buildscript {+    repositories {+        gradlePluginPortal()+    }++    dependencies {+        classpath 'com.palantir.gradle.externalpublish:gradle-external-publish-plugin:1.4.0'+        classpath 'com.palantir.gradle.gitversion:gradle-git-version:0.12.3'+    }+}++/**+ * Previously we used a shell script to publish the distribution to bintray. With the migration to maven-central, we+ * need to leverage more tooling coming from 'gradle-external-publish-plugin'. Based on that, this repo is currently+ * in an awkward split-mode. This Gradle setup is just for publishing the dist to maven-central. The actual build and+ * compilation is still done through yarn (see 'package.json').+ * TODO(fawind): Move this project fully to Gradle (i.e. using 'gradlets/gradle-typescript').+ */+apply plugin: 'com.palantir.external-publish-dist'+apply plugin: 'com.palantir.git-version'++group 'com.palantir.conjure.typescript'+version gitVersion()++task verifyBinariesExist() {+    [file('dist/bin/conjure-typescript'), file('dist/bin/conjure-typescript.bat')]

I think you need to put this in a doFirst/doLast or this code will run at configuration time rather than as a task action?

fawind

comment created time in 11 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentpalantir/gradle-conjure

move conjure generator tasks to task-avoidance APIs

 import org.gradle.api.tasks.PathSensitivity;  @CacheableTask-public class CompileConjureTypeScriptTask extends ConjureGeneratorTask {-    private final Property<String> packageName = getProject().getObjects().property(String.class);-    private final Property<String> packageVersion = getProject().getObjects().property(String.class);--    private File productDependencyFile;-+public abstract class CompileConjureTypeScriptTask extends ConjureGeneratorTask {     public CompileConjureTypeScriptTask() {         Project project = getProject();-        packageName.set(getProject().provider(project::getName));-        packageVersion.set(getProject().provider(() -> project.getVersion().toString()));+        getPackageName().convention(getProject().provider(project::getName));

Ah, from https://docs.gradle.org/7.2/userguide/lazy_configuration.html#applying_conventions:

Once a value is set, the convention is ignored

So this means if you set a convention after there is a value, it's a no-op, where as value/set would actually replace the value. Sounds like a useful tool - in this case sense we're calling convention right after making the properties it should be equivalent to value/set.

esword

comment created time in a month

PullRequestReviewEvent

Pull request review commentpalantir/gradle-conjure

move conjure generator tasks to task-avoidance APIs

 import org.gradle.api.tasks.PathSensitivity;  @CacheableTask-public class CompileConjureTypeScriptTask extends ConjureGeneratorTask {-    private final Property<String> packageName = getProject().getObjects().property(String.class);-    private final Property<String> packageVersion = getProject().getObjects().property(String.class);--    private File productDependencyFile;-+public abstract class CompileConjureTypeScriptTask extends ConjureGeneratorTask {     public CompileConjureTypeScriptTask() {         Project project = getProject();-        packageName.set(getProject().provider(project::getName));-        packageVersion.set(getProject().provider(() -> project.getVersion().toString()));+        getPackageName().convention(getProject().provider(project::getName));

I'm wondering what the difference between property.convention and property.value/set do. Both seem to set default values, but I haven't actually seen convention used until just now. I thought they might be name overloads but they do seem to have different behaviour in the code.

esword

comment created time in a month

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentpalantir/gradle-baseline

Java compilation warnings and errors are no longer limited to the first 100

+/*+ * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++package com.palantir.baseline.plugins;++import java.util.List;+import org.gradle.api.Plugin;+import org.gradle.api.Project;+import org.gradle.api.tasks.compile.JavaCompile;++/**+ * Applies the {@code -Xmaxwarns} and {@code -Xmaxerrs} compiler options with a very large+ * limit to avoid truncating failure info.+ */+public final class BaselineJavaCompilerDiagnostics implements Plugin<Project> {++    // Default maxwarns/maxerrs is only 100, which often makes it difficult to debug+    // annotation processing issues.+    private static final String MANY = "10000";++    private static final String MAX_WARNINGS_ARG = "-Xmaxwarns";+    private static final String MAX_ERRORS_ARG = "-Xmaxerrs";++    @Override+    public void apply(Project project) {+        project.getTasks().withType(JavaCompile.class).configureEach(javaCompileTask -> {+            List<String> compilerArgs = javaCompileTask.getOptions().getCompilerArgs();+            // Avoid overriding options that have already been set+            if (!compilerArgs.contains(MAX_WARNINGS_ARG)) {

Would we want this to work if people override after applying the plugin too? If so, we'd probably want to put this in a project.afterEvaluate to run after people have had a chance to change it.

carterkozak

comment created time in a month

issue commentaquasecurity/trivy

Avoid network request during JAR scans

This is really wrecking us as we do scans in air-gapped environments. We stopped upgrading the trivy binary to 0.17+ because of it, but now we're in a situation where we need to support alpine 3.14 so need at least 0.19.0, which puts us in a quandry.

Even an option to turn off jar scanning, or making it not do jar scans with --vuln-type os, would get out us of this sticky situation.

fawind

comment created time in a month

PullRequestReviewEvent

Pull request review commentpalantir/gradle-baseline

Implement LoggerInterpolationConsumesThrowable

+/*+ * (c) Copyright 2017 Palantir Technologies Inc. All rights reserved.+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++package com.palantir.baseline.errorprone;++import com.google.auto.service.AutoService;+import com.google.errorprone.BugPattern;+import com.google.errorprone.BugPattern.SeverityLevel;+import com.google.errorprone.VisitorState;+import com.google.errorprone.bugpatterns.BugChecker;+import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;+import com.google.errorprone.matchers.Description;+import com.google.errorprone.matchers.Matcher;+import com.google.errorprone.matchers.method.MethodMatchers;+import com.sun.source.tree.ExpressionTree;+import com.sun.source.tree.LiteralTree;+import com.sun.source.tree.MethodInvocationTree;+import com.sun.source.tree.Tree;+import java.util.List;++@AutoService(BugChecker.class)+@BugPattern(+        name = "LoggerInterpolationConsumesThrowable",+        link = "https://github.com/palantir/gradle-baseline#baseline-error-prone-checks",+        linkType = BugPattern.LinkType.CUSTOM,+        severity = SeverityLevel.ERROR,+        summary = "Logger call interpolation markers should not be used for the throwable parameter because they "+                + "prevent stack traces from being logged in favor of the string value of the Throwable.")+public final class LoggerInterpolationConsumesThrowable extends BugChecker implements MethodInvocationTreeMatcher {++    private static final Matcher<ExpressionTree> LOG_METHOD = MethodMatchers.instanceMethod()+            .onDescendantOfAny("org.slf4j.Logger", "com.palantir.logsafe.logger.SafeLogger")+            .namedAnyOf("trace", "debug", "info", "warn", "error", "fatal");++    private static final Matcher<ExpressionTree> MARKER = MoreMatchers.isSubtypeOf("org.slf4j.Marker");+    private static final Matcher<ExpressionTree> THROWABLE = MoreMatchers.isSubtypeOf(Throwable.class);++    @Override+    public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {+        if (!LOG_METHOD.matches(tree, state)) {+            return Description.NO_MATCH;+        }++        List<? extends ExpressionTree> args = tree.getArguments();+        // No need to verify logging calls with only a message+        if (args.size() <= 1) {+            return Description.NO_MATCH;+        }++        // Not problematic unless slf4j curly braces consume a throwable, so we can short-circuit out.+        int throwableIndex = args.size() - 1;+        ExpressionTree lastArg = args.get(throwableIndex);+        if (!THROWABLE.matches(lastArg, state)) {+            return Description.NO_MATCH;+        }++        boolean hasMarker = MARKER.matches(tree.getArguments().get(0), state);+        int messageIndex = hasMarker ? 1 : 0;+        ExpressionTree messageArg = args.get(messageIndex);++        if (messageArg.getKind() != Tree.Kind.STRING_LITERAL) {+            return Description.NO_MATCH;+        }++        String literalMessage = (String) ((LiteralTree) messageArg).getValue();+        int stringPlaceholders = countPlaceholders(literalMessage);+        int nonThrowableParameters = throwableIndex - messageIndex - 1;+        if (stringPlaceholders <= nonThrowableParameters) {+            return Description.NO_MATCH;+        }+        int extraPlaceholders = stringPlaceholders - nonThrowableParameters;+        return buildDescription(tree)

Might be interesting to track how many excavators fail to upgrade with this check, given we can't autofix them

carterkozak

comment created time in a month

PullRequestReviewEvent

pull request commentprobot/smee.io

Make the payload include the raw data of the delivery body.

Also needed for #78

fourdollars

comment created time in a month