mirror of
https://github.com/dhall-lang/dhall-kubernetes.git
synced 2024-09-17 10:27:08 +03:00
Nixify the build (#55)
This makes our build reproducible and consistent * Disables dhall tests. They don't build in sandbox mode because they require network access * Moves all scripts to ./scripts folder for consistency * Moves all nix files to ./nix folder for consistency, except for release.nix which Hydra needs * Changes convert.py to take the K8s swagger spec as an argument * Get k8s swagger spec from nixpkgs * Get dhall prelude from nixpkgs * added an ./scripts/update-nixpkgs.sh script to easily update to a new version of nixpkgs
This commit is contained in:
parent
f860c4e2a4
commit
8d295ecedc
15
Makefile
Normal file
15
Makefile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
.PHONY: install build check default
|
||||||
|
default: build
|
||||||
|
README.md: docs/README.md.dhall
|
||||||
|
./scripts/build-readme.sh
|
||||||
|
build: README.md
|
||||||
|
mkdir -p types default
|
||||||
|
./scripts/convert.py "${OPENAPI_SPEC}"
|
||||||
|
check: build
|
||||||
|
LC_ALL=en_US.UTF-8 ./scripts/check-source.py
|
||||||
|
mkdir -p tmp
|
||||||
|
LC_ALL=en_US.UTF-8 ./scripts/build-examples.py tmp
|
||||||
|
install: build
|
||||||
|
cp -r types default "${out}"
|
||||||
|
cp README.md "${out}"
|
||||||
|
|
22
README.md
22
README.md
@ -290,6 +290,15 @@ metadata:
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
### Updating the nixpkgs snapshot (and kubernetes version)
|
||||||
|
|
||||||
|
Run
|
||||||
|
```bash
|
||||||
|
./scripts/update-nixpkgs.sh
|
||||||
|
./generate.sh
|
||||||
|
```
|
||||||
|
If the tests fail, rollback. If they don't then you have sucessfully upgraded!
|
||||||
|
|
||||||
### Tests
|
### Tests
|
||||||
|
|
||||||
All tests are defined in `release.nix`. We run these tests in CI in a [Hydra
|
All tests are defined in `release.nix`. We run these tests in CI in a [Hydra
|
||||||
@ -301,12 +310,15 @@ You can run the tests locally with the following command:
|
|||||||
nix build --file ./release.nix
|
nix build --file ./release.nix
|
||||||
```
|
```
|
||||||
|
|
||||||
### Changing the README
|
### Generating `types` `default` and `README.md`
|
||||||
|
|
||||||
|
Running `scripts/generate.sh` will generate all dhall files from the kubernetes
|
||||||
|
swagger specification, and copy them to `types` and `default`. It will also
|
||||||
|
generate `README.md` from `docs/README.md.dhall`.
|
||||||
|
|
||||||
|
If you make changes to `scripts/convert.py` or `docs/README.md.dhall`, you need
|
||||||
|
to run this command afterwards.
|
||||||
|
|
||||||
We build `README.md` from `docs/README.md.dhall` and check it into source control.
|
|
||||||
The build script `./scripts/build-readme.sh` inlines source code from the
|
|
||||||
`examples` directory. If you make changes to the readme or the examples you need
|
|
||||||
to run `scripts/build-readme.sh`.
|
|
||||||
|
|
||||||
## Projects Using `dhall-kubernetes`
|
## Projects Using `dhall-kubernetes`
|
||||||
|
|
||||||
|
@ -123,6 +123,15 @@ ${../examples/out/ingressRaw.yaml as Text}
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
### Updating the nixpkgs snapshot (and kubernetes version)
|
||||||
|
|
||||||
|
Run
|
||||||
|
```bash
|
||||||
|
./scripts/update-nixpkgs.sh
|
||||||
|
./generate.sh
|
||||||
|
```
|
||||||
|
If the tests fail, rollback. If they don't then you have sucessfully upgraded!
|
||||||
|
|
||||||
### Tests
|
### Tests
|
||||||
|
|
||||||
All tests are defined in `release.nix`. We run these tests in CI in a [Hydra
|
All tests are defined in `release.nix`. We run these tests in CI in a [Hydra
|
||||||
@ -134,12 +143,15 @@ You can run the tests locally with the following command:
|
|||||||
nix build --file ./release.nix
|
nix build --file ./release.nix
|
||||||
```
|
```
|
||||||
|
|
||||||
### Changing the README
|
### Generating `types` `default` and `README.md`
|
||||||
|
|
||||||
|
Running `scripts/generate.sh` will generate all dhall files from the kubernetes
|
||||||
|
swagger specification, and copy them to `types` and `default`. It will also
|
||||||
|
generate `README.md` from `docs/README.md.dhall`.
|
||||||
|
|
||||||
|
If you make changes to `scripts/convert.py` or `docs/README.md.dhall`, you need
|
||||||
|
to run this command afterwards.
|
||||||
|
|
||||||
We build `README.md` from `docs/README.md.dhall` and check it into source control.
|
|
||||||
The build script `./scripts/build-readme.sh` inlines source code from the
|
|
||||||
`examples` directory. If you make changes to the readme or the examples you need
|
|
||||||
to run `scripts/build-readme.sh`.
|
|
||||||
|
|
||||||
## Projects Using `dhall-kubernetes`
|
## Projects Using `dhall-kubernetes`
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ mkDerivation {
|
|||||||
sha256 = "9b22cc6f7694ef2f5d5d6fa66727044622b9905b2a9da0cdf376c75ad3b9df0e";
|
sha256 = "9b22cc6f7694ef2f5d5d6fa66727044622b9905b2a9da0cdf376c75ad3b9df0e";
|
||||||
isLibrary = true;
|
isLibrary = true;
|
||||||
isExecutable = true;
|
isExecutable = true;
|
||||||
|
doCheck = false;
|
||||||
libraryHaskellDepends = [
|
libraryHaskellDepends = [
|
||||||
aeson aeson-pretty ansi-terminal base bytestring case-insensitive
|
aeson aeson-pretty ansi-terminal base bytestring case-insensitive
|
||||||
cborg cborg-json containers contravariant cryptonite Diff directory
|
cborg cborg-json containers contravariant cryptonite Diff directory
|
||||||
|
21
nix/dhall-kubernetes.nix
Normal file
21
nix/dhall-kubernetes.nix
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{lib, stdenv, dhall, dhall-json, dhall-text, dhallPackages, kubernetes-openapi-spec, python3, glibcLocales}:
|
||||||
|
let
|
||||||
|
# Ignore generated files
|
||||||
|
ignoreOutputs = name: type: !(lib.elem name (map toString [../README.md ../types ../default]));
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "dhall-kubernetes";
|
||||||
|
DHALL_PRELUDE = "${dhallPackages.prelude}/package.dhall";
|
||||||
|
OPENAPI_SPEC = "${kubernetes-openapi-spec}";
|
||||||
|
doCheck = true;
|
||||||
|
buildInputs = [ dhall dhall-json dhall-text python3 glibcLocales ];
|
||||||
|
preBuild = ''
|
||||||
|
patchShebangs ./scripts/build-readme.sh
|
||||||
|
patchShebangs ./scripts/convert.py
|
||||||
|
'';
|
||||||
|
preCheck = ''
|
||||||
|
patchShebangs ./scripts/build-examples.py
|
||||||
|
patchShebangs ./scripts/check-source.py
|
||||||
|
'';
|
||||||
|
src = lib.cleanSourceWith {filter = ignoreOutputs; src = lib.cleanSource ./..;};
|
||||||
|
}
|
9
nix/kubernetes-openapi-spec.nix
Normal file
9
nix/kubernetes-openapi-spec.nix
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{stdenv, kubernetes}:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "kubernetes-openapi-spec";
|
||||||
|
src = kubernetes.src;
|
||||||
|
phases = [ "unpackPhase" "installPhase" ];
|
||||||
|
installPhase = ''
|
||||||
|
cp api/openapi-spec/swagger.json $out
|
||||||
|
'';
|
||||||
|
}
|
7
nix/nixpkgs.json
Normal file
7
nix/nixpkgs.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"url": "https://github.com/nixos/nixpkgs-channels.git",
|
||||||
|
"rev": "07b42ccf2de451342982b550657636d891c4ba35",
|
||||||
|
"date": "2019-03-22T11:15:26+02:00",
|
||||||
|
"sha256": "1a7ga18pwq0y4p9r787622ry8gssw1p6wsr5l7dl8pqnj1hbbzwh",
|
||||||
|
"fetchSubmodules": false
|
||||||
|
}
|
24
nix/nixpkgs.nix
Normal file
24
nix/nixpkgs.nix
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
let
|
||||||
|
spec = builtins.fromJSON (builtins.readFile ./nixpkgs.json);
|
||||||
|
nixpkgs = builtins.fetchGit {
|
||||||
|
inherit (spec) url rev;
|
||||||
|
ref = "nixpkgs-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
packageOverrides = pkgs: rec {
|
||||||
|
dhall-kubernetes = pkgs.callPackage ./dhall-kubernetes.nix {};
|
||||||
|
kubernetes-openapi-spec = pkgs.callPackage ./kubernetes-openapi-spec.nix {};
|
||||||
|
haskellPackages = pkgs.haskellPackages.override {
|
||||||
|
overrides = haskellPackagesNew: haskellPackagesOld: rec {
|
||||||
|
dhall = haskellPackagesNew.callPackage ./dhall-1.21.0.nix {};
|
||||||
|
dhall-json = haskellPackagesNew.callPackage ./dhall-json-1.2.7.nix {};
|
||||||
|
dhall-text = haskellPackagesNew.callPackage ./dhall-text-1.0.16.nix {};
|
||||||
|
megaparsec = haskellPackagesNew.callPackage ./megaparsec-7.0.2.nix {};
|
||||||
|
repline = haskellPackagesNew.callPackage ./repline-0.2.0.0.nix {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
import nixpkgs { inherit config; }
|
24
nixpkgs.nix
24
nixpkgs.nix
@ -1,24 +0,0 @@
|
|||||||
let
|
|
||||||
rev = "19013d809297cb9dbba69bda24e52a2833f4e05a";
|
|
||||||
outputSha256 = "148nqqyb39xmxlnw4vgqin2s7ywq51yi64d2hqmd6pk2gqnhmpv9";
|
|
||||||
|
|
||||||
nixpkgs = builtins.fetchTarball {
|
|
||||||
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
|
|
||||||
sha256 = outputSha256;
|
|
||||||
};
|
|
||||||
|
|
||||||
config = {
|
|
||||||
packageOverrides = pkgs: rec {
|
|
||||||
haskellPackages = pkgs.haskellPackages.override {
|
|
||||||
overrides = haskellPackagesNew: haskellPackagesOld: rec {
|
|
||||||
dhall = haskellPackagesNew.callPackage ./nix/dhall-1.21.0.nix {};
|
|
||||||
dhall-json = haskellPackagesNew.callPackage ./nix/dhall-json-1.2.7.nix {};
|
|
||||||
dhall-text = haskellPackagesNew.callPackage ./nix/dhall-text-1.0.16.nix {};
|
|
||||||
megaparsec = haskellPackagesNew.callPackage ./nix/megaparsec-7.0.2.nix {};
|
|
||||||
repline = haskellPackagesNew.callPackage ./nix/repline-0.2.0.0.nix {};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
import nixpkgs { inherit config; }
|
|
66
release.nix
66
release.nix
@ -1,65 +1,17 @@
|
|||||||
{ src ? { rev = ""; }, ... }:
|
{ pkgs ? import ./nix/nixpkgs.nix
|
||||||
let
|
, src ? { rev = ""; }
|
||||||
pkgs = import ./nixpkgs.nix;
|
, ...
|
||||||
|
}:
|
||||||
nativeBuildInputs = [
|
rec {
|
||||||
pkgs.git
|
inherit (pkgs) dhall-kubernetes;
|
||||||
pkgs.python3
|
|
||||||
pkgs.bash
|
|
||||||
pkgs.dhall
|
|
||||||
pkgs.dhall-json
|
|
||||||
pkgs.dhall-text
|
|
||||||
pkgs.glibcLocales
|
|
||||||
];
|
|
||||||
|
|
||||||
runCommand = name: script:
|
|
||||||
pkgs.runCommand name { inherit nativeBuildInputs; } script;
|
|
||||||
|
|
||||||
generatedFilesCompile =
|
|
||||||
runCommand
|
|
||||||
"generated-files-compile"
|
|
||||||
''
|
|
||||||
cd ${./.}
|
|
||||||
LC_ALL=en_US.UTF-8 ./scripts/check-source.py
|
|
||||||
|
|
||||||
touch $out
|
|
||||||
'';
|
|
||||||
|
|
||||||
buildReadme =
|
|
||||||
runCommand
|
|
||||||
"build-readme"
|
|
||||||
''
|
|
||||||
cd ${./.}
|
|
||||||
./scripts/build-readme.sh $out
|
|
||||||
|
|
||||||
diff --unified --color=always README.md $out
|
|
||||||
'';
|
|
||||||
|
|
||||||
validateExamples =
|
|
||||||
runCommand
|
|
||||||
"validate-examples"
|
|
||||||
''
|
|
||||||
cd ${./.}
|
|
||||||
mkdir $out
|
|
||||||
LC_ALL=en_US.UTF-8 ./scripts/build-examples.py $out
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Derivation that trivially depends on the input source code revision.
|
# Derivation that trivially depends on the input source code revision.
|
||||||
# As this is included in the "dhall-lang" aggregate, it forces every
|
# As this is included in the "dhall-lang" aggregate, it forces every
|
||||||
# commit to have a corresponding GitHub status check, even if the
|
# commit to have a corresponding GitHub status check, even if the
|
||||||
# commit doesn't make any changes (which can happen when merging
|
# commit doesn't make any changes (which can happen when merging
|
||||||
# master in).
|
# master in).
|
||||||
rev = pkgs.runCommand "rev" {} ''echo "${src.rev}" > $out'';
|
rev = pkgs.runCommand "rev" {} ''echo "${src.rev}" > $out'';
|
||||||
|
aggregate = pkgs.releaseTools.aggregate {
|
||||||
|
name = "dhall-kubernetes-agggregate";
|
||||||
in {
|
constituents = [ dhall-kubernetes rev ];
|
||||||
dhall-kubernetes = pkgs.releaseTools.aggregate {
|
|
||||||
name = "dhall-kubernetes";
|
|
||||||
constituents = [
|
|
||||||
generatedFilesCompile
|
|
||||||
validateExamples
|
|
||||||
buildReadme
|
|
||||||
rev
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
|
import json
|
||||||
import requests
|
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
kubernetes_tag = 'v1.13.4'
|
|
||||||
url = \
|
|
||||||
'https://raw.githubusercontent.com/kubernetes/kubernetes/{tag}/api/openapi-spec/swagger.json' \
|
|
||||||
.format(tag=kubernetes_tag)
|
|
||||||
|
|
||||||
# See https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields
|
# See https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields
|
||||||
# because k8s API allows PUTS etc with partial data, it's not clear from the data types OR the API which
|
# because k8s API allows PUTS etc with partial data, it's not clear from the data types OR the API which
|
||||||
@ -132,53 +128,53 @@ def labelize(propName):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
spec = requests.get(url).json()
|
with open(sys.argv[1]) as specf:
|
||||||
|
spec = json.load(specf)
|
||||||
for modelName, modelSpec in spec['definitions'].items():
|
for modelName, modelSpec in spec['definitions'].items():
|
||||||
with open('types/' + modelName + '.dhall', 'w') as f:
|
with open('types/' + modelName + '.dhall', 'w') as f:
|
||||||
f.write('{}\n'.format(build_type(modelSpec, '.', modelName)))
|
f.write('{}\n'.format(build_type(modelSpec, '.', modelName)))
|
||||||
with open('default/' + modelName + '.dhall', 'w') as f:
|
with open('default/' + modelName + '.dhall', 'w') as f:
|
||||||
if 'type' in modelSpec:
|
if 'type' in modelSpec:
|
||||||
typ = build_type(modelSpec, '../types')
|
typ = build_type(modelSpec, '../types')
|
||||||
# In case we have a union, we make the constructors for it
|
# In case we have a union, we make the constructors for it
|
||||||
if typ[0] == '<':
|
if typ[0] == '<':
|
||||||
f.write('{}\n'.format(typ))
|
f.write('{}\n'.format(typ))
|
||||||
# Otherwise we just output the identity
|
# Otherwise we just output the identity
|
||||||
|
else:
|
||||||
|
f.write('\(a : {}) -> a\n'.format(typ))
|
||||||
|
elif '$ref' in modelSpec:
|
||||||
|
path = schema_path_from_ref('.', modelSpec['$ref'])
|
||||||
|
f.write('{}\n'.format(path))
|
||||||
else:
|
else:
|
||||||
f.write('\(a : {}) -> a\n'.format(typ))
|
required = required_properties(modelName, modelSpec)
|
||||||
elif '$ref' in modelSpec:
|
if modelName in required_for.keys():
|
||||||
path = schema_path_from_ref('.', modelSpec['$ref'])
|
required |= required_for[modelName]
|
||||||
f.write('{}\n'.format(path))
|
|
||||||
else:
|
|
||||||
required = required_properties(modelName, modelSpec)
|
|
||||||
if modelName in required_for.keys():
|
|
||||||
required |= required_for[modelName]
|
|
||||||
|
|
||||||
properties = modelSpec.get('properties', {})
|
properties = modelSpec.get('properties', {})
|
||||||
|
|
||||||
resource_data = get_static_data(modelSpec)
|
resource_data = get_static_data(modelSpec)
|
||||||
param_names = required - set(resource_data.keys())
|
param_names = required - set(resource_data.keys())
|
||||||
|
|
||||||
# If there's multiple required props, we make it a lambda
|
# If there's multiple required props, we make it a lambda
|
||||||
requiredProps = [k for k in properties if k in required]
|
requiredProps = [k for k in properties if k in required]
|
||||||
if len(requiredProps) > 0:
|
if len(requiredProps) > 0:
|
||||||
params = ['{} : ({})'.format(labelize(propName), build_type(propVal, '../types'))
|
params = ['{} : ({})'.format(labelize(propName), build_type(propVal, '../types'))
|
||||||
for propName, propVal in properties.items()
|
for propName, propVal in properties.items()
|
||||||
if propName in param_names]
|
if propName in param_names]
|
||||||
f.write('\(_params : {' + ', '.join(params) + '}) ->\n')
|
f.write('\(_params : {' + ', '.join(params) + '}) ->\n')
|
||||||
|
|
||||||
# If it's required we're passing it in as a parameter
|
# If it's required we're passing it in as a parameter
|
||||||
KVs = [(propName, "_params." + propName)
|
KVs = [(propName, "_params." + propName)
|
||||||
if propName in param_names
|
if propName in param_names
|
||||||
else (propName, get_default(propDef, propName in required, resource_data.get(propName, None)))
|
else (propName, get_default(propDef, propName in required, resource_data.get(propName, None)))
|
||||||
for propName, propDef in properties.items()]
|
for propName, propDef in properties.items()]
|
||||||
|
|
||||||
# If there's no fields, should be an empty record
|
# If there's no fields, should be an empty record
|
||||||
if len(KVs) > 0:
|
if len(KVs) > 0:
|
||||||
formatted = [" {} = {}\n".format(labelize(k), v) for k, v in KVs]
|
formatted = [" {} = {}\n".format(labelize(k), v) for k, v in KVs]
|
||||||
else:
|
else:
|
||||||
formatted = '='
|
formatted = '='
|
||||||
f.write('{' + ','.join(formatted) + '} : ../types/' + modelName + '.dhall\n')
|
f.write('{' + ','.join(formatted) + '} : ../types/' + modelName + '.dhall\n')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
12
scripts/generate.sh
Executable file
12
scripts/generate.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
rm -rf ./default ./types
|
||||||
|
if dir=$(nix-build release.nix -A dhall-kubernetes --no-out-link); then
|
||||||
|
cp -r "$dir"/default .
|
||||||
|
chmod u+w ./default
|
||||||
|
cp -r "$dir"/types .
|
||||||
|
chmod u+w ./types
|
||||||
|
cp "$dir/README.md" README.md
|
||||||
|
chmod u+w ./README.md
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
4
scripts/update-nixpkgs.sh
Executable file
4
scripts/update-nixpkgs.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#!nix-shell -i bash -p nix-prefetch-git
|
||||||
|
|
||||||
|
nix-prefetch-git https://github.com/nixos/nixpkgs-channels.git --rev refs/heads/nixos-unstable > ./nix/nixpkgs.json
|
Loading…
Reference in New Issue
Block a user