Skip to content

Commit f63a714

Browse files
authored
Merge pull request #1 from stuartleeks/sl/go
Convert to Go implementation, with the following advantages: * The application runs as a windowless app so there is no longer the flash of a powershell window when the task runs * The logic has been updated to test for a running WSL v2 distro before checking whether to reset the clock (rather than _any_ running distro). This removes the potential for spinning up a WSL 2 distro when there wasn't one running (i.e. when there was no need to reset the clock) * The logic now uses an existing running distro for executing the time checks and reset steps, rather than the default distro. This avoids situations where an extra distro may have been started, as well as avoiding issues when the default distro was configured as WSL v1
2 parents 38c40e6 + beebf3a commit f63a714

File tree

19 files changed

+707
-57
lines changed

19 files changed

+707
-57
lines changed

.devcontainer/Dockerfile

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#-------------------------------------------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
4+
#-------------------------------------------------------------------------------------------------------------
5+
6+
FROM golang:1.14-stretch
7+
8+
# Avoid warnings by switching to noninteractive
9+
ENV DEBIAN_FRONTEND=noninteractive
10+
11+
# Configure apt, install packages and tools
12+
RUN apt-get update \
13+
&& apt-get -y install --no-install-recommends apt-utils dialog nano \
14+
#
15+
# Verify git, process tools, lsb-release (common in install instructions for CLIs) installed
16+
&& apt-get -y install git iproute2 procps lsb-release \
17+
# Install Release Tools
18+
#
19+
# --> RPM used by goreleaser
20+
&& apt install -y rpm \
21+
# Clean up
22+
&& apt-get autoremove -y \
23+
&& apt-get clean -y \
24+
&& rm -rf /var/lib/apt/lists/*
25+
26+
# This Dockerfile adds a non-root user with sudo access. Use the "remoteUser"
27+
# property in devcontainer.json to use it. On Linux, the container user's GID/UIDs
28+
# will be updated to match your local UID/GID (when using the dockerFile property).
29+
# See https://aka.ms/vscode-remote/containers/non-root-user for details.
30+
ARG USERNAME=vscode
31+
ARG USER_UID=1000
32+
ARG USER_GID=$USER_UID
33+
34+
# Set env for tracking that we're running in a devcontainer
35+
ENV DEVCONTAINER=true
36+
37+
# Enable go modules
38+
ENV GO111MODULE=on
39+
40+
# Install Go tools
41+
RUN \
42+
# --> Delve for debugging
43+
go get github.com/go-delve/delve/cmd/[email protected] \
44+
# --> Go language server
45+
&& go get golang.org/x/tools/[email protected] \
46+
# --> Go symbols and outline for go to symbol support and test support
47+
&& go get github.com/acroca/[email protected] && go get github.com/ramya-rao-a/go-outline@7182a932836a71948db4a81991a494751eccfe77 \
48+
# --> GolangCI-lint
49+
&& curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sed 's/tar -/tar --no-same-owner -/g' | sh -s -- -b $(go env GOPATH)/bin \
50+
# --> Go releaser
51+
&& curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | sh -s -- "v0.132.1"\
52+
# --> Install junit converter
53+
&& go get github.com/jstemmer/[email protected] \
54+
&& rm -rf /go/src/ && rm -rf /go/pkg
55+
56+
# Switch back to dialog for any ad-hoc use of apt-get
57+
ENV DEBIAN_FRONTEND=dialog

.devcontainer/devcontainer.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
2+
// https://github.com/microsoft/vscode-dev-containers/tree/v0.117.1/containers/go
3+
{
4+
"name": "wsl-clock",
5+
"dockerFile": "Dockerfile",
6+
"runArgs": [
7+
// Uncomment the next line to use a non-root user. On Linux, this will prevent
8+
// new files getting created as root, but you may need to update the USER_UID
9+
// and USER_GID in .devcontainer/Dockerfile to match your user if not 1000.
10+
// "-u", "vscode",
11+
"--cap-add=SYS_PTRACE",
12+
"--security-opt",
13+
"seccomp=unconfined",
14+
15+
// Mount go mod cache
16+
"-v", "wsl-clock-gomodcache:/go/pkg",
17+
// Keep command history
18+
"-v", "wsl-clock-bashhistory:/root/commandhistory",
19+
// Mount docker socket for docker builds
20+
"-v", "/var/run/docker.sock:/var/run/docker.sock",
21+
// Use host network
22+
"--network=host",
23+
// Mount azure, git and docker config
24+
"-v", "${env:HOME}${env:USERPROFILE}/.azure:/root/.azure"
25+
],
26+
27+
// Set *default* container specific settings.json values on container create.
28+
"settings": {
29+
"terminal.integrated.shell.linux": "/bin/bash",
30+
"go.gopath": "/go",
31+
"go.useLanguageServer": true,
32+
"[go]": {
33+
"editor.snippetSuggestions": "none",
34+
"editor.formatOnSave": true,
35+
"editor.codeActionsOnSave": {
36+
"source.organizeImports": true,
37+
}
38+
},
39+
"gopls": {
40+
"usePlaceholders": true, // add parameter placeholders when completing a function
41+
// Experimental settings
42+
"completeUnimported": true, // autocomplete unimported packages
43+
"watchFileChanges": true, // watch file changes outside of the editor
44+
"deepCompletion": true, // enable deep completion
45+
},
46+
"files.eol": "\n", // formatting only supports LF line endings
47+
},
48+
49+
// Add the IDs of extensions you want installed when the container is created.
50+
"extensions": [
51+
"golang.go"
52+
]
53+
54+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
55+
// "forwardPorts": [],
56+
57+
// Use 'postCreateCommand' to run commands after the container is created.
58+
// "postCreateCommand": "go version",
59+
60+
// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
61+
// "remoteUser": "vscode"
62+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: build-and-release
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-18.04
12+
13+
steps:
14+
- uses: actions/checkout@v2
15+
16+
- name: CI Tooling
17+
run: sudo apt update && sudo apt install build-essential -y
18+
19+
- name: Build devcontainer for tooling
20+
run: sudo -E make devcontainer
21+
22+
- name: Run the release
23+
run: sudo -E make devcontainer-release
24+
env:
25+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26+
BUILD_NUMBER: ${{ github.run_id }}
27+
IS_CI: 1
28+
IS_PR: ${{ github.head_ref }}
29+
BRANCH: ${{ github.ref }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/wsl-clock
2+
/wsl-clock.exe
3+
/dist

.goreleaser.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
builds:
2+
- env:
3+
- CGO_ENABLED=0
4+
binary: wsl-clock
5+
goos:
6+
- windows
7+
goarch:
8+
- 386
9+
- amd64
10+
main: .
11+
ldflags:
12+
- -s -w -X main.version={{.Version}} -X main.commit={{.ShortCommit}} -X main.date={{.Date}} -X "main.goversion={{.Env.GOVERSION}}" -H windowsgui
13+
14+
archives:
15+
- id: zip
16+
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
17+
format_overrides:
18+
- goos: windows
19+
format: zip
20+
files:
21+
- README.md
22+
- LICENSE.md
23+
- add-wslclocktask.ps1
24+
- remove-wslclocktask.ps1
25+
26+
changelog:
27+
sort: asc
28+
filters:
29+
exclude:
30+
- '^docs:'
31+
- '^test:'

.vscode/launch.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Launch",
9+
"type": "go",
10+
"request": "launch",
11+
"mode": "auto",
12+
"program": "${fileDirname}",
13+
"env": {},
14+
"args": []
15+
},
16+
{
17+
"name": "Launch a test",
18+
"type": "go",
19+
"request": "launch",
20+
"mode": "auto",
21+
"program": "${file}",
22+
// "args": [
23+
// "-test.v",
24+
// "-test.run",
25+
// "^${selectedText}$"
26+
// ],
27+
"env": {
28+
"GOOS": "windows",
29+
},
30+
"buildFlags": "-v -tags=all",
31+
"showLog": true,
32+
"envFile": "${workspaceFolder}/.env"
33+
}
34+
]
35+
}

Makefile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
build:
2+
GOOS=windows go build .
3+
4+
lint: build
5+
GOOS=windows golangci-lint run
6+
7+
devcontainer:
8+
docker build -f ./.devcontainer/Dockerfile ./.devcontainer -t wsl-clock
9+
10+
devcontainer-release:
11+
ifdef DEVCONTAINER
12+
$(error This target can only be run outside of the devcontainer as it mounts files and this fails within a devcontainer. Don't worry all it needs is docker)
13+
endif
14+
@docker run -v ${PWD}:${PWD} \
15+
-e BUILD_NUMBER="${BUILD_NUMBER}" \
16+
-e IS_CI="${IS_CI}" \
17+
-e IS_PR="${IS_PR}" \
18+
-e BRANCH="${BRANCH}" \
19+
-e GITHUB_TOKEN="${GITHUB_TOKEN}" \
20+
--entrypoint /bin/bash \
21+
--workdir "${PWD}" \
22+
wsl-clock \
23+
-c "${PWD}/scripts/ci_release.sh"
24+
25+
26+
test:
27+
GOOS=windows go test -v ./...

README.md

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
**IMPORTANT: This is not an official solution and whilst it worked on my machine this is an unsupported workaround :-)**
44

5-
There is an issue with WSL where the clock in WSl isn't updated when the host resumes from sleep/hibernate. E.g. [this issue](https://github.com/microsoft/WSL/issues/4245)
5+
There is an issue with WSL where the clock in WSL isn't updated when the host resumes from sleep/hibernate. E.g. [this issue](https://github.com/microsoft/WSL/issues/4245)
66

77
This repo has a workaround that creates a scheduled task that is triggered by Windows Events for resuming from sleep/hibernation. When the scheduled task executes it resets the clock in the WSL VM.
88

9-
For the background to this repo, see [this blog post](https://stuartleeks.com/posts/fixing-clock-skew-with-wsl-2/)
9+
For the background to this repo, see [this blog post](https://stuartleeks.com/posts/fixing-clock-skew-with-wsl-2/). The implementation discussed in that blog post is based on PowerShell and that implementation is still available [here](https://github.com/stuartleeks/wsl-clock/tree/powershell). The implementation has now been replaced with a program written in Go, with the following advantages:
10+
11+
* The appliation runs as a windowless app so there is no longer the flash of a powershell window when the task runs
12+
* The logic has been updated to test for a running WSL v2 distro before checking whether to reset the clock (rather than _any_ running distro). This removes the potential for spinning up a WSL 2 distro when there wasn't one running (i.e. when there was no need to reset the clock)
13+
* The logic now uses an existing running distro for executing the time checks and reset steps, rather than the default distro. This avoids situations where an extra distro may have been started, as well as avoiding issues when the default distro was configured as WSL v1
1014

1115
## Setup
1216

@@ -18,23 +22,4 @@ To remove the scheduled task, run `remove-wslclocktask.ps1`
1822

1923
## Logs/Troubleshooting
2024

21-
The script invoked by the scheduled task logs output to `~/.wsl-clock.log`
22-
23-
## Known issues
24-
25-
### Fails if default distribution is configured for WSL 1
26-
27-
The `update-clock.ps1` script executes the `hwclock` against the default distro. If that distro is configured to run under WSL 1 then it will result in the following error as `hwclock` isn't supported on WSL 1 (and WSL 1 isn't executing in the lightweight VM for WSL 2 so this wouldn't have any effect anyway)
28-
29-
```log
30-
hwclock: Cannot access the Hardware Clock via any known method.
31-
hwclock: Use the --debug option to see the details of our search for an access method.
32-
```
33-
34-
See <https://github.com/microsoft/wsl/issues/193>.
35-
36-
Possible workarounds:
37-
38-
* change your default distro to a distro that is configured for WSL 2
39-
* change your default distro to run on WSL 2
40-
* modify your copy of the script to specify a distro via `-d` parameter for `wsl` when it runs `hwclock`
25+
The program invoked by the scheduled task logs output to `~/.wsl-clock.log`

add-wslclocktask.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
$taskCommand = "powershell.exe -noprofile -windowstyle Hidden -Command '" + $PSScriptRoot + "\update-clock.ps1'"
1+
$taskCommand = $PSScriptRoot + "\wsl-clock.exe"
22

33
schtasks /Create /TN wsl-clock /TR $taskCommand /SC ONEVENT /EC System /MO "*[System[Provider[@Name='Microsoft-Windows-Kernel-Power'] and (EventID=107 or EventID=507)]]" /F

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/stuartleeks/wsl-clock
2+
3+
go 1.14
4+
5+
require github.com/stretchr/testify v1.6.1

0 commit comments

Comments
 (0)