Skip to content

Commit a44e65d

Browse files
committed
Add manifests for winget package manager
The winget package manager uses MSIX installers. Create winget manifests for quick-lint-js which install using our MSIX installer.
1 parent 580147d commit a44e65d

File tree

8 files changed

+306
-0
lines changed

8 files changed

+306
-0
lines changed

.github/workflows/build-static.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,38 @@ jobs:
385385
remote-directory: ${{ secrets.artifacts_root }}/builds/${{ github.sha }}/windows/
386386
user: ${{ secrets.artifacts_user }}
387387

388+
package-winget:
389+
name: winget manifests
390+
needs: package-msix
391+
runs-on: ubuntu-latest
392+
container: ghcr.io/quick-lint/quick-lint-js-github-go-builder:v1
393+
steps:
394+
- name: checkout
395+
uses: actions/checkout@v2
396+
- uses: actions/download-artifact@v2
397+
with:
398+
name: quick-lint-js-msix-${{ github.sha }}
399+
path: ./
400+
401+
- name: create manifests
402+
run: go run ./dist/winget/make-manifests.go -BaseURI 'https://c.quick-lint-js.com/builds/${{ github.sha }}/' -MSIX ./quick-lint-js.msix -OutDir winget-manifests
403+
404+
- name: upload manifests to workflow
405+
uses: actions/upload-artifact@v3
406+
with:
407+
if-no-files-found: error
408+
name: quick-lint-js-winget-${{ github.sha }}
409+
path: winget-manifests/
410+
- name: upload manifests to long-term storage
411+
if: ${{ github.event_name == 'push' && github.repository_owner == 'quick-lint' != null }}
412+
uses: quick-lint/sftp-upload@master
413+
with:
414+
host: ${{ secrets.artifacts_host }}
415+
local-file-globs: winget-manifests/*
416+
private-key: ${{ secrets.artifacts_key }}
417+
remote-directory: ${{ secrets.artifacts_root }}/builds/${{ github.sha }}/winget/
418+
user: ${{ secrets.artifacts_user }}
419+
388420
# quick-lint-js finds bugs in JavaScript programs.
389421
# Copyright (C) 2020 Matthew Glazar
390422
#

dist/release.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ var Steps []Step = []Step{
3636
fmt.Printf("* dist/npm/BUILDING.md\n")
3737
fmt.Printf("* dist/npm/package.json\n")
3838
fmt.Printf("* dist/sign-release.go\n")
39+
fmt.Printf("* dist/winget/quick-lint.quick-lint-js.installer.template.yaml\n")
40+
fmt.Printf("* dist/winget/quick-lint.quick-lint-js.locale.en-US.template.yaml\n")
41+
fmt.Printf("* dist/winget/quick-lint.quick-lint-js.template.yaml\n")
3942
fmt.Printf("* plugin/vim/quick-lint-js.vim/doc/quick-lint-js.txt\n")
4043
fmt.Printf("* plugin/vscode-lsp/README.md\n")
4144
fmt.Printf("* plugin/vscode-lsp/package.json\n")
@@ -106,6 +109,15 @@ var Steps []Step = []Step{
106109
},
107110
},
108111

112+
Step{
113+
Title: "Create a winget manifest",
114+
Run: func() {
115+
fmt.Printf("Create a winget manifest:\n")
116+
fmt.Printf("$ go run ./dist/winget/make-manifests.go -BaseURI \"https://c.quick-lint-js.com/release/$YOUR_VERSION_NUMBER/\" -MSIX signed-builds/windows/quick-lint-js.msix -OutDir signed-builds/winget/\n")
117+
WaitForDone()
118+
},
119+
},
120+
109121
Step{
110122
Title: "Upload the signed build artifacts",
111123
Run: func() {

dist/winget/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# quick-lint-js winget manifest
2+
3+
This directory contains manifests for [Windows Package Manager][winget] aka
4+
winget.
5+
6+
The `make-manifests.go` script modifies the `.yaml` files.
7+
8+
## Testing
9+
10+
To test quick-lint-js' winget manifests, perform the following steps on your
11+
Windows machine:
12+
13+
1. Download a signed `quick-lint-js.msix` from a `windows` directory in
14+
<https://c.quick-lint-js.com/releases/>.
15+
2. Create a directory called `windows` and put `quick-lint-js.msix` inside it.
16+
3. Outside the `windows` directory, start a static HTTP server. For example,
17+
run: `npx http-server -p 8069` The HTTP server must support `GET` requests
18+
with `Range`. (Python's `http.server` does not support this.)
19+
4. Build the manifests: run
20+
`go run dist/winget/make-manifests.go -BaseURI http://localhost:8069/ -MSIX path\to\windows\quick-lint-js.msix -OutDir test-winget-manifests`
21+
5. Install the manifests: `winget install --manifest test-winget-manifests`
22+
23+
## Publishing
24+
25+
Every build, [CI](../../.github/workflows/build-static.yml) updates URLs in YAML
26+
files to refer to https://c.quick-lint-js.com/builds/COMMIT_HASH/, hashes the
27+
referenced installer files, adds the hashes to the YAML files, and uploads the
28+
modified YAML files to https://c.quick-lint-js.com/builds/COMMIT_HASH/winget/.
29+
30+
When [making a release](../../docs/RELEASE.md), the release engineer updates
31+
URLs in YAML files to refer to https://c.quick-lint-js.com/releases/VERSION/,
32+
hashes the referenced installer files, adds the hashes to the YAML files, and
33+
uploads the modified YAML files to
34+
https://c.quick-lint-js.com/releases/VERSION/winget/.
35+
36+
[winget]: https://docs.microsoft.com/en-us/windows/package-manager/

dist/winget/make-manifests.go

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright (C) 2020 Matthew "strager" Glazar
2+
// See end of file for extended copyright information.
3+
4+
package main
5+
6+
import "crypto/sha256"
7+
import "flag"
8+
import "fmt"
9+
import "io"
10+
import "io/ioutil"
11+
import "log"
12+
import "os"
13+
import "path/filepath"
14+
import "regexp"
15+
import "runtime"
16+
import "text/template"
17+
18+
var BaseURI string
19+
var MSIXPath string
20+
var OutDirPath string
21+
22+
var WingetSourcePath string
23+
24+
var BaseURIRegexp *regexp.Regexp = regexp.MustCompile(`^https?://.*/$`)
25+
26+
type TemplateVariables struct {
27+
BaseURI string
28+
MSIXSHA256 string
29+
}
30+
31+
func main() {
32+
flag.StringVar(&BaseURI, "BaseURI", "", "")
33+
flag.StringVar(&MSIXPath, "MSIX", "", "")
34+
flag.StringVar(&OutDirPath, "OutDir", "", "")
35+
flag.Parse()
36+
if BaseURI == "" {
37+
fmt.Fprintf(os.Stderr, "error: missing -BaseURI\n")
38+
os.Exit(2)
39+
}
40+
if !BaseURIRegexp.MatchString(BaseURI) {
41+
fmt.Fprintf(os.Stderr, "error: invalid -BaseURI; must match regular expression: %v\n", BaseURIRegexp.String())
42+
os.Exit(2)
43+
}
44+
if MSIXPath == "" {
45+
fmt.Fprintf(os.Stderr, "error: missing -MSIX\n")
46+
os.Exit(2)
47+
}
48+
if OutDirPath == "" {
49+
fmt.Fprintf(os.Stderr, "error: missing -OutDir\n")
50+
os.Exit(2)
51+
}
52+
53+
_, scriptPath, _, ok := runtime.Caller(0)
54+
if !ok {
55+
panic("could not determine path of .go file")
56+
}
57+
WingetSourcePath = filepath.Dir(scriptPath)
58+
59+
if err := Main(); err != nil {
60+
log.Fatal(err)
61+
}
62+
}
63+
64+
func Main() error {
65+
if err := os.MkdirAll(OutDirPath, 0755); err != nil {
66+
return err
67+
}
68+
69+
msixSHA256, err := SHA256File(MSIXPath)
70+
if err != nil {
71+
return err
72+
}
73+
variables := TemplateVariables{
74+
BaseURI: BaseURI,
75+
MSIXSHA256: msixSHA256,
76+
}
77+
78+
filesToTransform := map[string]string{
79+
"quick-lint.quick-lint-js.installer.template.yaml": "quick-lint.quick-lint-js.installer.yaml",
80+
"quick-lint.quick-lint-js.locale.en-US.template.yaml": "quick-lint.quick-lint-js.locale.en-US.yaml",
81+
"quick-lint.quick-lint-js.template.yaml": "quick-lint.quick-lint-js.yaml",
82+
}
83+
for templatePath, outputPath := range filesToTransform {
84+
if err := TransformTemplateFile(
85+
filepath.Join(WingetSourcePath, templatePath),
86+
filepath.Join(OutDirPath, outputPath),
87+
variables,
88+
); err != nil {
89+
return err
90+
}
91+
}
92+
93+
return nil
94+
}
95+
96+
func TransformTemplateFile(templatePath string, outputPath string, variables TemplateVariables) error {
97+
templateSource, err := ioutil.ReadFile(templatePath)
98+
if err != nil {
99+
return err
100+
}
101+
tmpl, err := template.New(templatePath).Parse(string(templateSource))
102+
if err != nil {
103+
return err
104+
}
105+
106+
outputFile, err := os.Create(outputPath)
107+
if err != nil {
108+
return err
109+
}
110+
defer outputFile.Close()
111+
if err := tmpl.Execute(outputFile, variables); err != nil {
112+
return err
113+
}
114+
115+
return nil
116+
}
117+
118+
func SHA256File(path string) (string, error) {
119+
file, err := os.Open(path)
120+
if err != nil {
121+
return "", err
122+
}
123+
defer file.Close()
124+
hasher := sha256.New()
125+
if _, err := io.Copy(hasher, file); err != nil {
126+
return "", err
127+
}
128+
return fmt.Sprintf("%x", hasher.Sum(nil)), nil
129+
}
130+
131+
// quick-lint-js finds bugs in JavaScript programs.
132+
// Copyright (C) 2020 Matthew "strager" Glazar
133+
//
134+
// This file is part of quick-lint-js.
135+
//
136+
// quick-lint-js is free software: you can redistribute it and/or modify
137+
// it under the terms of the GNU General Public License as published by
138+
// the Free Software Foundation, either version 3 of the License, or
139+
// (at your option) any later version.
140+
//
141+
// quick-lint-js is distributed in the hope that it will be useful,
142+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
143+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144+
// GNU General Public License for more details.
145+
//
146+
// You should have received a copy of the GNU General Public License
147+
// along with quick-lint-js. If not, see <https://www.gnu.org/licenses/>.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# To the extent possible under law, Matthew "strager" Glazar
2+
# has waived all copyright and related or neighboring rights
3+
# to _quick-lint-js winget manifests_. This work is
4+
# published from United States.
5+
# http://creativecommons.org/publicdomain/zero/1.0/
6+
7+
PackageIdentifier: quick-lint.quick-lint-js
8+
PackageVersion: 2.3.0.0
9+
10+
Installers:
11+
- InstallerUrl: {{ .BaseURI }}windows/quick-lint-js.msix
12+
InstallerSha256: {{ .MSIXSHA256 }}
13+
InstallerType: msix
14+
Platform:
15+
- Windows.Desktop
16+
- Windows.Universal
17+
MinimumOSVersion: 10.0.0.0
18+
Architecture: x64
19+
PackageFamilyName: fa6b940b-8f96-4b46-8e21-703a63133e06_y724facbts4te
20+
21+
ManifestType: installer
22+
ManifestVersion: 1.1.0
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# To the extent possible under law, Matthew "strager" Glazar
2+
# has waived all copyright and related or neighboring rights
3+
# to _quick-lint-js winget manifests_. This work is
4+
# published from United States.
5+
# http://creativecommons.org/publicdomain/zero/1.0/
6+
7+
PackageIdentifier: quick-lint.quick-lint-js
8+
PackageVersion: 2.3.0.0
9+
PackageLocale: en-US
10+
11+
PackageName: quick-lint-js
12+
PackageUrl: https://quick-lint-js.com/
13+
ShortDescription: 'Find bugs in JavaScript programs.'
14+
Moniker: quicklintjs
15+
16+
Publisher: quick-lint
17+
PublisherSupportUrl: https://quick-lint-js.com/contact/
18+
Copyright: 'Copyright (C) 2020 Matthew "strager" Glazar'
19+
License: 'GPL-3.0-or-later,...'
20+
21+
Tags:
22+
- bugs
23+
- code-quality
24+
- errors
25+
- javascript
26+
- js
27+
- lint
28+
- linter
29+
- linting
30+
- quick-js-lint
31+
- static-analysis
32+
- strager
33+
- syntax
34+
35+
ManifestType: defaultLocale
36+
ManifestVersion: 1.1.0
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# To the extent possible under law, Matthew "strager" Glazar
2+
# has waived all copyright and related or neighboring rights
3+
# to _quick-lint-js winget manifests_. This work is
4+
# published from United States.
5+
# http://creativecommons.org/publicdomain/zero/1.0/
6+
7+
PackageIdentifier: quick-lint.quick-lint-js
8+
PackageVersion: 2.3.0.0
9+
10+
DefaultLocale: en-US
11+
ManifestType: version
12+
ManifestVersion: 1.1.0

tools/check-file-copyrights

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ check_file_copyright_header() {
1515
case "${file}" in
1616
benchmark/benchmark-lsp/corpus/*) ;;
1717
benchmark/benchmark-lsp/*) check_file_copyright_header_benchmark_lsp "${file}" ;;
18+
dist/winget/*.yaml) check_file_copyright_header_winget_manifests "${file}" ;;
1819
*) check_file_copyright_header_quick_lint_js "${file}" ;;
1920
esac
2021
}
@@ -28,6 +29,14 @@ check_file_copyright_header_quick_lint_js() {
2829
fgrep -q 'quick-lint-js is free software' "${file}"
2930
}
3031

32+
# quick-lint-js's winget manifests are under the public
33+
# domain (CC0).
34+
check_file_copyright_header_winget_manifests() {
35+
local file="${1}"
36+
fgrep -q 'waived all copyright' "${file}" && \
37+
fgrep -q 'quick-lint-js winget manifests' "${file}"
38+
}
39+
3140
# quick-lint-js's benchmark-lsp subproject is BSD3-licensed.
3241
check_file_copyright_header_benchmark_lsp() {
3342
local file="${1}"

0 commit comments

Comments
 (0)